在函数文字中省略下划线?

时间:2012-02-24 06:49:35

标签: scala

scala> val alist = List(1,2,3,4,5)
alist: List[Int] = List(1, 2, 3, 4, 5)

scala> alist filter { 2.< }
res2: List[Int] = List(3, 4, 5)

scala> alist filter { 2 < }
res3: List[Int] = List(3, 4, 5)

scala> alist filter { > 3 }
<console>:1: error: ';' expected but integer literal found.
       alist filter { > 3 }

为什么{ 2.< }{2 <}有效?我想至少我应该写{ 2 < _ }吧?

一个不需要参数的方法,你可以选择不加点并使用post fi x运算符表示法:

scala> val s = "Hello, world!"
s: java.lang.String = Hello, world!
scala> s toLowerCase
res4: java.lang.String = hello, world!

但是在这里,<方法不是那些不需要参数的方法吗?

你能指出我的用法是什么吗?

3 个答案:

答案 0 :(得分:2)

原因是2是一个对象,所以如果你写2.<2 <(在Scala中实际上是相同的),那么你正在调用一个方法{对象<上的{1}}。

如果您只是编写2<,编译器将在本地范围内查找此类方法,但找不到。类似地,编写>,编译器需要一个可用的方法> 3,而不是。

您还可以直接在控制台中看到此行为:

>

如您所见,定义了几个含义,将scala> 3.< <console>:8: error: ambiguous reference to overloaded definition, both method < in class Double of type (x: Char)Boolean and method < in class Double of type (x: Short)Boolean match expected type ? 3.< ^ 转换为定义3方法的类的对象。所以这在原则上是有效的,但不能独立存在。但是,如果你有更多的类型信息,那就可以了。

将此与以下内容进行对比:

<

在这里,您可以看到编译器在某处寻找独立的scala> <(3) <console>:8: error: not found: value < <(3) ^ 。请注意,错误消息显示值,但这仍然意味着它可能是一个函数,因为值类型可能是<或类似的东西。

答案 1 :(得分:1)

正在发生的是 Eta扩展(6.26.5):

  

Eta-expansion将方法类型的表达式转换为等价物   功能类型的表达。

在这种情况下,2 <是一种方法类型:<上的方法Int。但是,filter需要一个函数类型。在这种情况下,Scala会进行自动扩展。

请注意,由于filter预期的类型已知,因此可以正确推断出正在调用的2 <方法。

答案 2 :(得分:1)

2.< 引用到对象<的方法2,而2.<(_)返回新函数一个论点。后者是(扩展为)(x: Int) => 2 < x的快捷方式,其中类型Int由scala编译器根据alist元素的类型推断。

在您的情况下,

> 3不引用任何对象的任何方法或对象。 >是一个合法的标量标识符(对于方法,函数或对象),但3不是合法标识符(以数字开头)。 > a可以是对象a>)的成员>.a的引用。但是你的例子中都没有这些。但是_ > 3会返回一个带有一个参数的新函数,您也可以编写(x: Int) => x > 3

这实质上与Daniel C. Sobral的回答和incrop对Frank的答案的评论相同,但不那么正式,有更多的例子。希望这有助于获得直觉。