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!
但是在这里,<
方法不是那些不需要参数的方法吗?
你能指出我的用法是什么吗?
答案 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的答案的评论相同,但不那么正式,有更多的例子。希望这有助于获得直觉。