scala中的eta-conversion

微博上“甲骨文java社区”给了一段java8的lambda表达的例子,然后撒迦同学 指出:

其实 number -> String.valueOf(number) 可以写成 String::valueOf 。Java 8的lambda支持这种eta-转换。

看着这个所谓的eta-转换很眼熟,scala中也支持,但之前从没弄清楚过它还有这么个“学术名词”。搜索了一下:eta是希腊字母 η, 发音“A塔”,也叫 η-conversion

scala规范的文档中没有找到eta-conversion的介绍,倒是找到eta-expansion
看了一下这里对eta-expansion的介绍

eta-expansion 与 eta-conversion 不是一回事;eta扩展指是把一个普通方法转换为函数对象的过程:
比如下面三种情况

1) val f = foo _ 
2) val f: (Int, Int) => Int = foo 
3) val f = foo(_, _) 

但是 : foo(_, 1) 不是合格的Eta扩展,it just expands to (a) => foo(a, 1)

回到eta-conversion,在haskell的文档中定义的很清楚:http://www.haskell.org/haskellwiki/Eta_conversion

《programming in scala》提到过这种形式,却没有提这个学术名词,而是很含混的一笔带过,让人以为是编译器“耍聪明”,而不了解这背后的理论依据(不过好像scala的作者也似乎在PIS一书中刻意避免去提一些抽象的名词)。

用scala看一下eta-conversion

//典型的,foreach的例子
scala> Array(1,2,3).foreach(println)
1
2
3

//自定义一个
scala> def foo(a:Any)(f:Any=>Unit) =  f(a)
foo: (a: Any)(f: Any => Unit)Unit

//完整方式,第二个参数是一段完整的lambda表达式 
scala> foo(2){(a:Any)=>println(a)}
2
//eta-转换
scala> foo(3){println}
3
//通常的缩写方式 
scala> foo(4){println _}
4

scala里 a => foo(a) 经过eta-conversion后,直接就是右边的函数名foo
而看起来java8里eta-conversion后的这个函数名还要做些”明确的修饰”, String.foo必须写为String::foo

scala中的eta-conversion》上有1条评论

  1. Pingback引用通告: 再谈eta-conversion与eta-expansion | 在路上

发表评论

电子邮件地址不会被公开。 必填项已用*标注