你能在Scala中返回一个可赋值的左值吗?

时间:2010-04-15 00:08:59

标签: scala

(注意, lvalue 实际上是来自C语法的术语,我不知道它在Scala中的名称!)

尝试学习Scala ...今晚我正在使用内部DSL来处理可能类似于PHP语法的动态范围语言。

我的REPL是:欢迎使用Scala版本2.7.6.final(Java HotSpot(TM)客户端VM,Java 1.6.0)。

我有一些简化的示例代码:


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");}
}

以下按预期方式工作:

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

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

另一方面,为什么以下不调用1参数更新方法?

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

在做一些试验和错误时,我发现了这种语法上的好奇心:

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_
         ^

上面覆盖“this_”的含义是什么?它去哪儿了?

最终,我希望这项工作:

a->'x = "blah"

由于

2 个答案:

答案 0 :(得分:8)

def this_= { print("hello") }

您似乎认为这是方法this_等于{ print("hello") }。相反,这是方法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

然而,当您巧合地使用具有特殊含义的语法(id_=)时,它只是一个标识符。任何标识符都会混合使用字母数字字符和其他符号,由下划线字符分隔。

最后,不,Scala中没有可赋值的左值。你可以这样:

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

例如,你可以这样做:

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)

=本身就是保留的。并且,顺便说一句,Scala中没有通过引用传递 - 您将永远无法更改作为参数传递的变量的值。

答案 1 :(得分:1)

我认为你需要的是隐式转换。

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,我相信你不应该使用$作为标识符,它通常用在编译器生成的类/函数中。