Why is the `unary_` prefix needed in scala?

后端 未结 2 1697
暗喜
暗喜 2021-01-30 22:31

Beginner Scala question, but I couldn\'t find the answer on here.

Similar to overloading in C++, I would expect the compiler can tell the difference between a method cal

相关标签:
2条回答
  • 2021-01-30 23:01

    The unary_ prefix for unary prefix operators is a bit misleading: it's more about the prefix part than the unary part. You need some way to distinguish

    !foo // unary prefix !
    

    from

    foo! // unary postfix !
    

    Remember: Scala doesn't actually have operators. There are two ways to call a method, either with a . or with whitespace:

    foo.bar(1, "two")
    foo bar(1, "two")
    

    And when you have a single argument, you can leave off the parentheses:

    foo plus(1)
    foo plus 1
    

    Lastly, (almost) any character is legal in an identifier:

    foo plus 1
    foo + 1
    

    Now it looks like Scala has a binary infix + operator, but it actually doesn't. It's just a normal method called with normal method calling syntax.

    What I said above isn't fully true, however. If Scala didn't have support for operators and it all was just normal method calling, then

    2 + 3 * 4
    

    would evaluate to 20 (like it does in Smalltalk, Self and Newspeak for example) instead of 14. So, there is a little bit of support for operators in Scala (two little bits, actually). When a method is called with whitespace (so-called "operator syntax") instead of the ., and that method starts with an operator character, then Scala will respect operator precedence.

    And the other little bit of operator support is that there are some operators that you would like to have, but that cannot be easily expressed as a method call. It works fine for binary infix operators and unary postfix operators:

    foo op bar // same as:
    foo.op(bar)
    
    foo op     // same as:
    foo.op
    

    But not for prefix or "around-fix" operators:

    !foo
    foo(bar)
    

    So, there are a couple of special syntactic sugar translation rules:

    !foo
    foo.unary_!
    // same for +, - and ~
    
    foo(bar)
    foo.apply(bar)
    
    foo(bar) = 1
    foo.update(bar, 1)
    
    foo += 1
    foo.+=(1) // but if this doesn't compile, then the compiler will also try
    foo = foo.+(1)
    

    And the reason why there needs to be an underscore between the alphanumeric and the "operator" part in a method name is because you wouldn't know whether

    foo!
    

    means

    foo.!
    

    or

    this.foo!
    

    Thus, foo! as a method name is illegal, it needs to be called foo_!.

    0 讨论(0)
  • 2021-01-30 23:01

    Because in scala it is totally fine to create a method named -, that takes no arguments. How would you distinguish between a normal and a unary method? For example ! has a totally different meaning as unary, than as post fix operator.

    0 讨论(0)
提交回复
热议问题