Scala 的“后缀操作”
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/13011204/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Scala's "postfix ops"
提问by dmitry
I've searched for a half-hour, and still cannot figure it out.
找了半天,还是没弄明白。
In SIP: Modularizing Language Featuresthere are a number of features which will require explicit "enabling" in Scala 2.10 (import language.feature).
Amongst them there is postfixOps, to which I just cannot find a reference anywhere. What exactly does this feature allow?
在SIP: Modularizing Language Features 中有许多功能需要在 Scala 2.10 ( import language.feature) 中显式“启用” 。其中有postfixOps,我在任何地方都找不到参考。此功能究竟允许什么?
回答by Kim Stebel
It allows you to use operator syntax in postfix position. For example
它允许您在后缀位置使用运算符语法。例如
List(1,2,3) tail
rather than
而不是
List(1,2,3).tail
In this harmless example it is not a problem, but it can lead to ambiguities. This will not compile:
在这个无害的例子中,这不是问题,但可能会导致歧义。这不会编译:
val appender:List[Int] => List[Int] = List(1,2,3) ::: //add ; here
List(3,4,5).foreach {println}
And the error message is not very helpful:
并且错误消息不是很有帮助:
value ::: is not a member of Unit
It tries to call the :::method on the result of the foreachcall, which is of type Unit. This is likely not what the programmer intended. To get the correct result, you need to insert a semicolon after the first line.
它尝试根据调用:::结果调用该方法foreach,该方法的类型为Unit。这可能不是程序员的意图。要获得正确的结果,您需要在第一行后插入一个分号。
回答by Alex
The simplest answer ever:
有史以来最简单的答案:
Dropping dot from methods without parameters is DEPRECATED!
从方法删除不用点参数是不推荐使用!
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)
OK to drop dot in methods that take one parameter of higher order functionlike map, filter, count and be safe! Also, purely functionalmethods like zip.
可以在使用高阶函数的一个参数的方法中删除点,例如 map、filter、count 并且安全!此外,像 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)
Long answer WHY
长答案为什么
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)Postfix operator - is actually a method call with no parameters (a!==a.!) and without brackets. (considered not safe and deprecated)
1)后缀操作符——实际上是一个没有参数(a!==a.!)且没有括号的方法调用。(被认为不安全且已弃用)
val b1 = MyBool(false) !!!
List(1,2,3) head
2)Postfix operator is method, that should end the line, or else it will be treated as infix.
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)Infix operator is method with one parameter, that can be called without dot and parentheses. Only for purely functionalmethods
3) 中缀运算符是带一个参数的方法,可以不带点和括号调用。仅用于纯函数方法
val c1 = MyBool(true) or b1 or MyBool(true)
val c2 = MyBool(true).or(b1).or(MyBool(true))
c1 == c2
4)Method with one or more parameters will chain without dot if you call it with parameters. def a(), def a(x), def a(x,y) But you should do this only for methods that use higher order functionas parameter!
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)
Sample warnings:
示例警告:
warning: there were 1 deprecation warning(s); re-run with -deprecation for details warning: postfix operator tail should be enabled by making the implicit value scala.language.postfixOps visible. This can be achieved by adding the import clause 'import scala.language.postfixOps' or by setting the compiler option -language:postfixOps. See the Scala docs for value scala.language.postfixOps for a discussion why the feature should be explicitly enabled.
警告:有 1 个弃用警告;使用 -deprecation 重新运行以获取详细信息警告:应通过使隐式值 scala.language.postfixOps 可见来启用后缀运算符尾部。这可以通过添加导入子句“import scala.language.postfixOps”或设置编译器选项 -language:postfixOps 来实现。有关为什么应该显式启用该功能的讨论,请参阅 Scala 文档中的值 scala.language.postfixOps。
回答by Régis Jean-Gilles
It refers to the ability to call a nullary (with no arg list or empty arg list) method as a postfix operator:
它指的是调用 nullary(没有 arg 列表或空 arg 列表)方法作为后缀运算符的能力:
By example:
举例:
case class MyBool(value: Boolean) {
def negated = new MyBool(!value)
}
val b1 = MyBool( true )
val b2 = b1 negated // Same as b1.negated

