How does Scala recognize "_" as space in the setter construct(_=), while "_" is allowed being the part of a function/property name?

I wanna know the mechanism or working behind how scala compiler recognises the different between _ used in different context for example.

 class a {
private var _x = 0
def x = _x
def x_= (nval:Int):Unit = _x = nval 
val p = new a
p.x  = 1
p.x_= 1

All the above value assignment works.
Same time scala complier recognize var _varnam=0. But here it does not take _ as space. Can someone explain me about how scala goes and match _= setter construct.

Please format your code properly by enclosing it in triple backticks. You could also paste your code into and provide a link here, so we can easily explore what you’re referring to.

Then, I cannot really make sense of what you’re asking. And your code seems to be ill-formed…


Yeah thank you now i have formatted it properly.

Spaces are irrelevant to the Scala compiler when parsing.

There is nothing special about the _ when being part of an identifier.

The special rule is simply that when the compiler encounters an assignment p.x = v it looks for a setter function called x_= accepting an argument of type v.

1 Like

Here is an introductory explanation of how getters and setters work in Scala:


Spaces are a red herring. x_= is a valid identifier, but x= isn’t. (operator characters in identifiers can’t follow any character other than _ or another operator character). The longest match rule parses in the first case x_= as an indentifier, and in the second case x as an identifier, than = as a second identifier.


yeah it say how to define getters and setters, doesn’t explains the internal magic how x = something invokes the method x_= even though we have have just mentioned in the code x = something.

The compiler rewrites p.x = 42 to p.x_=(42) if a getter+setter-pair is available.

The gory details of the “magic” is available in the language spec in sections 4.2 and 5.3 here:

Here is a REPL session with an example:

scala> class P { 
  var theX = 42
  def x = theX
  def x_=(v: Int): Unit = theX = v 

scala> val p = new P
val p: P = P@4866e0a7

scala> p.theX
val res5: Int = 42

scala> p.x
val res0: Int = 42

scala> p.x_=(43)  // an explicit call to the method x_=

scala> p.x
val res1: Int = 43

scala> p.theX
val res2: Int = 43

scala> p.x = 44   // this is "magically" rewritten to a call to p.x_=(44)
// mutated p.x

scala> p.x
val res3: Int = 44

scala> p.theX
val res4: Int = 44

The underlying variable should be made private (here called theX but often called _x as it can’t be called x as both fields and methods are in the same name space (in contrast to Java)), but I made it public here to expose the magic :slight_smile: