Scala right associative methods

2019-06-27 06:00发布

问题:

I am learning Scala, and playing with right associate unapply object. I know that if the name ends with ':' then it becomes right associative. However, there seems to be some strange restrictions on the naming

e.g. These are invalid

object cons: { def unapply(value: String): Option[(Char, List[Char])] = ??? }
object :_cons_: { def unapply(value: String): Option[(Char, List[Char])] = ??? }

These are valid

object cons_: { def unapply(value: String): Option[(Char, List[Char])] = ??? }
object >>: { def unapply(value: String): Option[(Char, List[Char])] = ??? }

So there seems to be some weirdness about mixing alpha-numeric characters and symbols in identifiers.

So basically, I want to have a descriptive name i.e. 'cons' and still have right associativity. Also, I would like my operator to be symetric for aesthetic reasons :-), so I dont really like cons_:
Is there a way to make something associate to the right without using a colon? Or any other suggestions to achieve this?

:_cons_: seems to be the closest, but, for some reason the identifier can't start with ':' and have alphanumerics

回答1:

From the spec (section 1.1):

There are three ways to form an identifier. First, an identifier can start with a letter which can be followed by an arbitrary sequence of letters and digits. This may be followed by underscore ‘_’ characters and another string composed of either letters and digits or of operator characters. Second, an identifier can start with an operator character followed by an arbitrary sequence of operator characters. The preceding two forms are called plain identifiers. Finally, an identifier may also be formed by an arbitrary string between back-quotes (host systems may impose some restrictions on which strings are legal for identifiers). The identifier then is composed of all characters excluding the backquotes themselves.

So it looks like you're out of luck—if your identifier starts with a : it can't contain non-operator characters. Note, though, that you can write the following (which isn't intended to do anything meaningful—just to demonstrate the syntax):

scala> class X { def `:cons:`(i: Int) = i }
defined class X

scala> val x = new X
x: X = X@6a665da6

scala> 1 `:cons:` x
res1: Int = 1

The method name still ends with a colon, so you get the right associativity you're looking for.