设计概要

设计概要

注释

// 注释
/* 注释 */

内置类型

[bool, byte, char, short, int, unit]    // 值类型
[String, List, Map]      // 对象

变量定义

var i: int = 0;

// 列表
var l: List<int> = [1, 2, 3, 4, 5];
l[0] = 1;

// 字典
var m: Map<int->string> = {
  "a" -> 1,
  "b" -> 2
}
m["a"] = 1;

// 函数
var x: int => int = (p:int) => p

函数定义

def add(a:int,b:int):int = {
  return  a+b;
}

first class function

def addx(x:int): int => int = {
   return (a:int) => x+a;
}

类定义

class A extends B {
public/private/protected:
  var a:int = 0;
  // 构造函数
  def A(a:int) = {
     this.a = a;
  }
  // 成员函数
  def s() = {
    print(this.a);
  }
}

接口

这里的接口相当于java的interface,只不过在类外实现。

  • 最普通的接口
interface showable
{
  def show(this:This);
}
// 为非泛型类实现trait
impl showable for int
{
  def show(this:int) = {
    print(this);
  }
}
1.show() // 合法
// 为泛型类实现trait
template<A,B>
class Pair{
public:
  def Pair(a:A, b:B) = {
    this.a = a;
    this.b = b;
  }
  var a:A;
  var b:B;
}

// 全泛化
template<A,B>
impl showable for Pair<A,B>
{
  def show(this) = {
    print(a,b);
  }
}
// 偏特化,带有泛型约束
template<A,B>
where A: extends Object impl Hash 
      B: extends Object impl Hash
impl showable for Pair<A,B>  
{
  def show(this:Pair<A,B>) = {
    print(a.hashCode(),b.hashCode());
  }
}
// 实体化
impl showable for Pair<int,int>
{
  def show(this:Pair<int,int>) = {
    print(a,b);
  }
}
  • 泛型接口
    这里演示一个泛型接口的问题,即因为命名冲突,一个泛型接口无法被实现两次:
template<T>
interface Get
{
  def get(this:This):T 
}

impl Get<int> for int {
  def get(this:int):int {
    return this;
  }
}

impl Get<String> for int {
  def get(this:int):String {
    return this.toString()
  }
}
1.get() // ambiguous, which one to choose?

泛型接口的本质是要对接口规定方法的类型签名做出限制,但是确实存在如上的问题。

怎么解决?去掉泛型接口。但是可以用concept来绕过。

算了吧还是留着吧,反正java也这样。

concept

interface偏重扩展类的行为,而concept偏重约束类的特征。

concept必须拥有类的完全访问权?这点还是待定吧,不一定有这样的需求吧。

前面的例子:

concept Get<T,Result>
{
  def get(x:T):Result;
}

instance Get<int,int>
{
  def get(x:int):int = {
    return x;
  }
}

instance Get<int,String>
{
  def get(x:int):String = {
    return x.toString();
  }
}

Get<int,int>::get(1);    // 合法, = 1
Get<int,String>::get(2); // 合法, = "2"

完美解决。

下面看一个更一般的例子,实现一个幺半群(有满足结合律的加法和单位元)。
scala代码:

abstract class SemiGroup[A] {
  def add(x: A, y: A): A
}
abstract class Monoid[A] extends SemiGroup[A] {
  def unit: A
}
object ImplicitTest extends App {
  implicit object StringMonoid extends Monoid[String] {
    def add(x: String, y: String): String = x concat y
    def unit: String = ""
  }
  implicit object IntMonoid extends Monoid[Int] {
    def add(x: Int, y: Int): Int = x + y
    def unit: Int = 0
  }
  def sum[A](xs: List[A])(implicit m: Monoid[A]): A =
    if (xs.isEmpty) m.unit
    else m.add(xs.head, sum(xs.tail))

  println(sum(List(1, 2, 3)))       // uses IntMonoid implicitly
  println(sum(List("a", "b", "c"))) // uses StringMonoid implicitly
}

Hint代码:

template<A>
concept SemiGroup {
  def add(x: A, y: A): A
}

template<A>
concept Monoid combine SemiGroup
{
  def unit():A;
}

instance SemiGroup<String> {
    def add(x: String, y: String): String = {
      return x+y;
   }
}
instance Monoid<String>{
  def unit():String {
    return "";
  }
}

instance SemiGroup<int> {
    def add(x: int, y: int): int = {
      return x+y;
   }
}
instance Monoid<int>{
  def unit():int{
    return 0;
  }
}

template<A>
where A: instance Monoid<A>
def sum(xs: List[A]): A = {
  if (xs.isEmpty) 
    // 这里的‘Monoid’是简写形式,允许你直接使用instance限制里出现的concept
    return Monoid::unit() 

  return Monoid::add(xs.head, sum(xs.tail)) 
}

可以发现二者的不同,concept偏向于短代码的组合,而没有继承链这一说。还有一个优势是,在你需要类型SemiGroup<int>这种形式的参数时,我们已经实现过它了。而目前并没有这样的隐式值。

需要注意一点,如同类继承,concept不能有循环依赖。

template <A>
concept SemiGroup
where a: instance SemiGroup // 错误!依赖自身!
{
  def add(x: A, y: A): A
}
template <A>
concept SemiGroup
where a: instance Monoid<A> // 错误!循环依赖!
{
  def add(x: A, y: A): A
}

template <A>
concept Monoid
where A: instance SemiGroup<A>
{
  def unit():A;
}

解决方法是按声明顺序识别依赖关系,如果一个concept依赖另一个尚未声明的concept,直接报错即可。

concept结合OO

可以看到concept和泛型的abstract class功能好像是相似的,怎么解决这个问题?

解决了,concept是对类型的限制,比如Monoid[A]表明类型A满足幺半群的公理,即类型本身满足公理。而class内部定义类的数据和行为。也就是一个是外部的限制,一个是自身的行为。

template <Elem, Result, template F<_>>
concept Functor {
  def fmap(x: Elem =>Result): F<Elem> => F<Result>   
}

// 偏特化
template<Elem, Result>
instance Functor<Elem, Result, List<Elem>> {
  override def fmap(func: Elem => Result): List<Elem> => List<Result> = {
    return list => list.map(func);
    // 做自动类型推导
    // 等价于 return (list:List<Elem>):List<Result> => list.map(func)
  }
}

// 偏特化
template<Elem, Result>
instance Functor<Elem, Result, Option<Elem>> {
  override def fmap(func: Elem => Result): Option<Elem> => Option<Result> = {
    return m => {
       return switch m {
         case null => null;
         case Some(e) => Some(func(e));
       }
    }
  }
}

// 于是
var l:List<int> = [1,2,3,4];
var f = Functor<int, String, List<int>>::fmap( x => x.toString());
// 最好能够自动推导,写成
var g = Functor::fmap( (x:int) => x.toString() )

f(l); // 结果 = ["1","2","3","4"]

想要用高阶类型不得不使用template语法。。。

template <A,B,C>
concept AddEq {
  def add(x:A,y:B):C
}

instance AddEq<int,int,int> {
  override def add(x:int,y:int):int = {
     return x+y;
  }
}

template <T>
instance AddEq<T,T,String> {
  override def add(x:T,y:T):String = {
     return x.toString()
  }
}

template<T>
def add(x:T,y:T)

再考虑一个concept和高阶类型的区别:

// 泛型类实现
template<Elem>
class Stack {
  var data:Array<T>;
  var pos:int;
  def Stack() {
    data = new Array<T>();
  }
  def pop(e:Elem) {    
    pos = pos - 1;   
  }
  def push(e:Elem) {
    data[pos] = e;
    pos = pos + 1;   
  }
  def top():Elem {
    return data[pos-1];
  }
}

linq (糖

var l:List[int] = [-1,-2,0,1,2];
from a in l
  from b in l
    from c in l
where a > 0 && b>0 && c>0
select (a,b,c);

模式匹配 (糖

// 注意switch是语句,不是表达式
switch x {
  case 1 => xxx; // 不用break
  case a:string => xxx;
  case A(a,b) => xxx;
  default: xxx;
}

递归模板

data List a = Nil | Cons a (List a)
template <T>
type List<T> = null | Cons<T, List<T> >

项目规划

  • if、while、操作符、var/val
  • 继承、sealed
  • 接口
  • lambda
  • 泛型类、泛型接口
  • linq查询表达式
  • case class和模式匹配
  • concept

高级特性看进度考虑加入:

  • 反射
  • 表达式树
  • 注解

一些细节:

  • typedef/typealias
  • 嵌套类型、嵌套函数声明
  • 模板字符串
  • object
  • 设计模式语法层简化
  • scala类似中缀操作符的一些语法糖
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,761评论 5 460
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,953评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,998评论 0 320
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,248评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,130评论 4 356
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,145评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,550评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,236评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,510评论 1 291
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,601评论 2 310
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,376评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,247评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,613评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,911评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,191评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,532评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,739评论 2 335

推荐阅读更多精彩内容

  • MySQL 索引设计概要 转自:http://draveness.me/sql-index-intro.html在...
    vonhng阅读 420评论 0 0
  • MySQL 索引设计概要 在 MySQL 中,页的大小一般为 16KB,不过也可能是 8KB、32KB 或者其他值...
    Kee丶阅读 311评论 0 0
  • 看完山下英子的《断舍离》之后,我本来想写一篇《从看得见到看不见》,因为一直没有好好静下心来想明白一些事情,所以迟迟...
    海豚的微笑阅读 482评论 0 0
  • 一、什么是多线程 一个iOS程序就像一个圆,不断循环,直到将它切断。一个运行着的程序就是一个进程或者叫做一个任务,...
    小沫360阅读 13,152评论 4 28
  • 期中考结束,终于又得空码字,这两天不写东西我手都痒痒了(噗哈哈哈哈) 今天写的主题是围绕《我们仨》来写的,书的篇幅...
    春风凉意阅读 428评论 2 6