Scala's "postfix ops"

ScalaScala 2.10

Scala Problem Overview


I've searched for a half-hour, and still cannot figure it out.

In SIP: Modularizing Language Features there 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?

Scala Solutions


Solution 1 - Scala

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 foreach call, 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.

Solution 2 - Scala

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 function like map, filter, count and be safe! Also, purely functional methods like 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)

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.

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 functional methods

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 function as parameter!

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.

Solution 3 - Scala

It refers to the ability to call a nullary (with no arg list or empty arg list) method as a postfix operator:

By example:

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

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestiondmitryView Question on Stackoverflow
Solution 1 - ScalaKim StebelView Answer on Stackoverflow
Solution 2 - ScalaAlexView Answer on Stackoverflow
Solution 3 - ScalaRégis Jean-GillesView Answer on Stackoverflow