scala类型系统:7) 中缀类型

scala类型系统:7) 中缀类型

中缀类型并不是一种特殊的类型,只是针对带有2个类型参数的泛型类型在表达方式上允许用中缀形式而已。


scala中的中缀表达在3个地方存在:操作符、模式匹配、类型声明

1)中缀操作符最常见: a + b 或 x foo y 里的+foo都是中缀操作符(严格的说scala里没有操作符,其实都是方法)。

其中需要注意的一点是名称最后以“:”结尾的,调用顺序与普通中缀操作符想反:从右往左。比如h :: t 实际是 t.::(h),它的意义在于可以让表达看起来更“顺眼”一些。比如我们自定义一个:

// 一个Cache单例,提供了 >>: 方法
scala> object Cache { def >>:(data:String) { println(data) } }
defined module Cache

scala> "myData" >>: Cache
myData

上面的方法很直观,让人一看就容易理解是把数据追加到cache中。还可以支持连续操作,稍修改一下:

scala> object Cache { def >>:(data:String):Cache.type = { println(data); Cache } }
defined module Cache

scala> "data2" >>: "data1" >>: Cache
data1
data2
res6: Cache.type = Cache$@45d2d12f

实际中,最常见的从右往左结合的中缀操作符是 List 的 :: 方法

scala> val list = List()
list: List[Nothing] = List()

scala> "A" :: "B" :: list
res4: List[String] = List(A, B)

2) 当一个高阶类型有2个参数化类型,比如

scala> class Foo[A,B]

在声明变量类型时,也可以用 A Foo B 中缀形式来表达,Foo也称为中缀类型

scala> val x: Int Foo String = null

即 Int Foo String 等同于 Foo[Int,String]

3) 包含两个参数的构造器,在模式匹配时也可以用中缀表达

scala> case class Cons(a:String,b:String)
defined class Cons

scala> val x = Cons("one", "two")
x: Cons = Cons(one,two)

scala> x match { case "one" Cons "two" => println("ok") }
ok

即 "one" Cons "two" 等同于 Cons("one", "two")

对于2)和3)似乎也体现了某种一致性,不过暂对中缀类型的好处没有体会,对于类型系统中的这种风格也还不了解,暂不做比较。

现实中有个很容易迷惑人的地方,常用的 List ,即存在了一个:: 方法, 也存在了一个:: 名字的case类(List的子类)。

所以,构造一个list可以通过::的伴生对象提供的工厂方法,也可以通过Nil的::方法

scala> val l = ::("A",Nil) // 这里::是伴生对象, 相当于 ::.apply()
l: scala.collection.immutable.::[String] = List(A)

scala> val l2 = "A" :: Nil // 这里::是方法, 相当于 Nil.::()
l2: List[String] = List(A)

scala> l == l2
res1: Boolean = true

在模式匹配时,可以用中缀形式:

// 这里::是伴生对象,相当于 ::.unapply()
case head :: tail => …

所以::在不同的场景,意思不同,有时是方法名,有时是伴生对象名。这个设计,最初了解时很爱吐槽。但它提供了一种看上去很一致的表象,在中缀形式下都是表示”头”与”尾”的连接。

转载自:http://hongjiang.info/scala/   推荐大家阅读下这位大哥出版的书《Scala函数式编程》

展开阅读全文

没有更多推荐了,返回首页