62

我已经搜索了半个小时,仍然无法弄清楚。

SIP:模块化语言特性中,有许多特性需要在 Scala 2.10 ( import language.feature) 中明确“启用”。其中有postfixOps,我在任何地方都找不到参考。这个功能到底允许什么?

4

3 回答 3

63

它允许您在后缀位置使用运算符语法。例如

List(1,2,3) tail

而不是

List(1,2,3).tail

在这个无害的例子中,这不是问题,但它可能会导致歧义。这不会编译:

val appender:List[Int] => List[Int] = List(1,2,3) ::: //add ; here
List(3,4,5).foreach {println}

并且错误消息不是很有帮助:

    value ::: is not a member of Unit

它尝试在调用:::结果上调用该方法,该结果foreachUnit. 这可能不是程序员的本意。要获得正确的结果,您需要在第一行之后插入一个分号。

于 2012-10-22T12:17:09.257 回答
36

有史以来最简单的答案:

从没有参数的方法中删除点已弃用

List(1,2,3) reverse //is bad style and will lead to unpredicted behaviour
List(1,2,3) map(_*2) reverse //bad too, because reverse can take first method call from the next line (details below)

可以在采用map、filter、count 等高阶函数参数的方法中删除 dot并确保安全!此外,纯函数方法,如 zip。

List(1,2,3) map(_*2) filter(_>2)
(List(1,2,3) map(_*2)).reverse //safe and good
List(1,3,5) zip List(2,4,6)

长答案为什么

case class MyBool(x: Boolean) {
  def !!! = MyBool(!x) //postfix
  def or(other: MyBool): MyBool = if(x) other else this //infix
  def justMethod0() = this //method with empty parameters
  def justMethod2(a: MyBool, b: MyBool) = this //method with two or more
  override def toString = if(x) "true" else "false"
}

1)后缀运算符 - 实际上是一个没有参数 (a!==a.!) 且没有括号的方法调用。(被认为不安全且已弃用)

val b1 = MyBool(false) !!!
List(1,2,3) head

2)后缀运算符是方法,应该结束行,否则将被视为中缀。

val b1 = MyBool(true) no! no! //ERROR
//is actually parsed like
val b2 = MyBool(true).no!(no!) //(no!) is unknown identifier
//as bad as
Vector(1,2,3) toList map(_*2) //ERROR

3)中缀操作符是一个参数的方法,可以在没有点和括号的情况下调用。仅适用于纯函数方法

val c1 = MyBool(true) or b1 or MyBool(true)
val c2 = MyBool(true).or(b1).or(MyBool(true))
c1 == c2

4)如果你用参数调用它,带有一个或多个参数的方法将不带点链接。def a(), def a(x), def a(x,y) 但是你应该只对使用高阶函数作为参数的方法这样做!

val d1 = MyBool(true) justMethod2(b1, c1) or b1 justMethod0() justMethod2(c1, b1)
//yes, it works, but it may be confusing idea
val d2 = MyBool(true).justMethod2(b1,c1).or(b1).justMethod0().justMethod2(c1, b1)
d1 == d2
//looks familiar? This is where it should be used:
List(1,2,3) filter(_>1) map(_*2)

示例警告:

警告:有 1 个弃用警告;使用 -deprecation 重新运行以获取详细信息警告:后缀运算符尾部应通过使隐式值 scala.language.postfixOps 可见来启用。这可以通过添加导入子句 'import scala.language.postfixOps' 或通过设置编译器选项 -language:postfixOps 来实现。请参阅 Scala 文档以获取值 scala.language.postfixOps 以讨论为什么应显式启用该功能。

于 2014-06-25T18:57:43.290 回答
5

它指的是调用 nullary(没有 arg 列表或空 arg 列表)方法作为后缀运算符的能力:

举例:

case class MyBool(value: Boolean) {
    def negated = new MyBool(!value)
}
val b1 = MyBool( true )
val b2 = b1 negated // Same as b1.negated

见:http ://www.scala-lang.org/node/118

于 2012-10-22T12:16:47.450 回答