tags:

views:

126

answers:

5

I want to do this:

var (a, b) = (0, 0)
a = (b = 100) 

but Scala is complaining that

error: type mismatch;
 found   : Unit
 required: Int

What I want is to assign a and b to the same value. Why Scala make it Unit where it should be Int?

+2  A: 

Why ask why? Assignment expressions have type Unit and that's how it is. No chained assignments. Period.

Randall Schulz
Why ask why? Because I find it doesn't make sense. Java has it, Ruby has it, why Scala make it different?
Phương Nguyễn
Because Scala doesn't want to be those languages. It's the same reason Scala doesn't have a break statement; to encourage you to leave the imperative baggage you brought from Java and Ruby at the door.
pelotom
Weeeelllll, I hate to bring it up, but Scala has a break statement nowadays (since 2.8). But you have to import it (import scala.util.control.Breaks._) so I guess no one will ever use it, and that is probably exactly what was intended :-)
olle kullberg
+4  A: 

Your statement is an assignment, which returns Unit. See this related question for reasons why. You can do this, if you want:


scala> var (a,b) = (0,0)
a: Int = 0
b: Int = 0

scala> a = {b = 100; b}
a: Int = 100
Arjan Blokzijl
Thanks for the link. Martin was explaining that he want to make Scala faster. Probably I want to make a comment on the original link
Phương Nguyễn
+2  A: 

You can define a special assignment operator (it must end with a colon as it must be right associative) for your own types, or write a generic wrapper (including implit conversions) for general types. I wouldn't recommend to actually use this, but here it goes:

  case class M[T](var t:T) {
    def =: (m: M[T]):M[T] = {m.t = t ; this}
  }

  implicit def anyToM[T](v:T) = M(v)
  implicit def mToAny[T](m:M[T]) = m.t

  def main(args: Array[String]) {
    var a = M(0)
    var b = M(0)
    var c = M(0)
    a =: b =: c =: 100
    println(a + b + c) //--> 300
  }

I think it is always a bad idea to summon heavy magick in order to save a few keystrokes. In Germany we would call this "to shoot sparrows with a cannon"...

Landei
+1  A: 
case class assign[T](v: T) {                           
  def to(vals: (T => Unit)*) { vals.foreach{ vv => vv(v) } }
}

var (a,b) = (0,0)

assign(39) to (a = _, b = _)

assert(a == 39)
assert(b == 39)

Or you can rename it to emulate a rather simple version of a with statement.

with(20) do (a = _, b = _, print)
Debilski
+2  A: 
scala> var a,b,c,d,e,f,g = 0
a: Int = 0
b: Int = 0
c: Int = 0
d: Int = 0
e: Int = 0
f: Int = 0
g: Int = 0

scala> var f,i,j,k,m,n,o = new Object{}
f: java.lang.Object = $anon$1@11ce012
i: java.lang.Object = $anon$2@baf4ae
j: java.lang.Object = $anon$3@15e68d
k: java.lang.Object = $anon$4@1d3633c
m: java.lang.Object = $anon$5@118317f
n: java.lang.Object = $anon$6@15998cb
o: java.lang.Object = $anon$7@13e6f83

scala>
Eastsun
Nice trick. Thanks.
Phương Nguyễn