5
votes

(note, lvalue is actually a term from the C grammar, I don't know what it's called in Scala!)

Trying to learn Scala... this evening I'm working on an internal DSL for a dynamically scoped language that might resemble PHP syntax.

My REPL is: Welcome to Scala version 2.7.6.final (Java HotSpot(TM) Client VM, Java 1.6.0).

I have some made-up example code:


class $(any: Any) {
    def update(sym: Symbol, any: Any) { println("line 2 executed");}
    def ->(sym: Symbol) : $ = { println("line 1 executed"); return this  }
    def update(any: Any) { println("line 3 executed");}
}

The following works as expected:

scala> var a = new $(0)
a: $ = $@19238ad

scala> a('x) = "blah"
line 2 executed

On the other hand, why does the following not invoke the 1-parameter update method?

scala> a = 1
:6: error: type mismatch;
 found   : Int(1)
 required: $
       a = 1
           ^

While doing some trial and error, I found this syntactical curiousity:

scala> class A { def this_= { print("hello") } }
defined class A

scala> var a = new A
a: A = A@9aca82

scala> a = 2
:6: error: type mismatch;
 found   : Int(2)
 required: A
       a = 2
           ^

scala> a.this_
:7: error: value this_ is not a member of A
       a.this_
         ^

What is the meaning over overriding "this_" above? Where does it go?

Ultimately, I would like this to work:

a->'x = "blah"

Thanks

2
The last example doesnt work because the method is actually this_= not this_ The = isnt required when defining a method (although if not used, the method will return Unit) and without the space between the two scalac just assumed you wanted the method this_=. Im fairly sure what you want to do isnt possible with the = method since its special, but it would be easily doable with some other function (eg <-, <=)Jackson Davis

2 Answers

8
votes
def this_= { print("hello") }

You seem to think this is the method this_ that is equal to { print("hello") }. Instead, this is the method this_=, which uses the procedure style declaration (ie, no equal sign).

It is most often used like this:

scala> class A {
     |   private var _x = ""
     |   def x = _x
     |   def x_=(s: String) = _x = s.toUpperCase
     | }
defined class A

scala> new A
res0: A = A@1169fb2

scala> res0.x
res1: java.lang.String =

scala> res0.x = "abc"

scala> res0.x
res2: java.lang.String = ABC

However, while you coincidentally used a syntax (id_=) which has special meaning, it is just an identifier. Any identifier many mix alphanumeric characters and other symbols, separarted by the underscore character.

Finally, no, there's no assignable lvalue in Scala. You can have things like this:

id(key) = value // with update
id.key = value  // with key_=, as long as key also exists and is public
id += value     // or any other method containing "=" as part of its name

For instance, you could do this:

scala> class A {
     |   private var _x = ""
     |   def :=(s: String) = _x = s.toUpperCase
     |   override def toString = "A("+_x+")"
     | }
defined class A

scala> val x = new A
x: A = A()

scala> x := "abc"

scala> x
res4: A = A(ABC)

But =, by itself, is reserved. And, by the way, there's no pass by reference in Scala -- you'll never be able to change the value of a variable passed as a parameter.

1
votes

I think what you need is implicit conversion.

scala> case class Test (val x: Int)  
defined class Test

scala> implicit def testFromInt (x: Int) = new Test (x)
testFromInt: (Int)Test

scala> var a = new Test (3)
a: Test = Test(3)

scala> a = 10
a: Test = Test(10)

BTW, I believe you should not use $ as identifier, its usually used in compiler generated class/function.