Scala's infix notation with object +, why not

2020-08-17 18:18发布

问题:

I can name objects like this, but can't call m:

object + {
  def m (s: String) = println(s)
}

Can't call +.m("hi"):

<console>:1: error: illegal start of simple expression
       +.m("hi")

Also can't call + m "hi" (preferred for DSL-usage).

But with object ++ it works fine! Do they conflict with (not existent) unary_+ methods? Is it possible to avoid this?

回答1:

Indeed it is not possible with unary operators. If you want to call it anyways, you could resort to using the name generated by the compiler for the JVM (which starts with a dollar):

scala> object + {
     | def m( s: String ) = println(s)
     | }
defined module $plus

scala> +.m("hello")
<console>:1: error: illegal start of simple expression
       +.m("hello")
        ^

scala> $plus.m("hello")
hello


回答2:

I believe the problem is that in order to handle unary operators without ambiguity, scala relies on a special case: only !, +, - and ~ are treated as unary operators. Thus in +.m("hi"), scala treat + as an unary operator and can't make sense of the whole expression.



回答3:

Another code using package:

object Operator extends App {
    // http://stackoverflow.com/questions/13367122/scalas-infix-notation-with-object-why-not-possible
    pkg1.Sample.f
    pkg2.Sample.f
}

package pkg1 {
    object + {
        def m (s: String) = println(s)
    }

    object Sample {
        def f = {
            // +.m("hi") => compile error: illegal start of simple expression
            // + m "hi" => compile error: expected but string literal found.
            $plus.m("hi pkg1")
            $plus m "hi pkg1"
        }
    }
}

package pkg2 {
    object + {
        def m (s: String) = println(s)
    }

    object Sample {
        def f = {
            pkg2.+.m("hi pkg2")
            pkg2.+ m "hi pkg2"
            pkg2.$plus.m("hi pkg2")
            pkg2.$plus m "hi pkg2"
        }
    }
}

java version "1.7.0_09"

Scala code runner version 2.9.2



标签: scala