Reputation: 95
If I can do this:
var num: Int = 1
num += 1
print(num)
Why can’t I do this? What would be the correct way? Fails on line 4
var num: Int = 1
def someFunction(num:Int){
num += 1
}
someFunction(num)
print(num)
Thanks for any insight. I've done some searching but nothing too helpful. I am mostly looking for the theory behind why this fails. I have accomplished what I need to with for statements but I am still wondering why this fails. Thanks!
Upvotes: 0
Views: 125
Reputation: 16412
It's a similar behavior to what you would see in Java. In Java and Scala you pass by value. A reference to your object/argument is copied and passed into the function. Thus, even if you would be able to change the value of that reference (num:Int
) you would be working with a copy of that value - essentially a reassignment. Reassignment to arguments is allowed in Java by default but not in Scala. In other words there is nothing like C/C++ has where you can reference external variable and modify its value. That being said you can still achieve similar effect if the value you are trying to modify is an object field:
// I'm changing it directly but you could have a setter instead:
scala> class A(var m: Int)
defined class A
scala> val a = new A(0)
a: A = A@469c3554
scala> a.m
res0: Int = 0
scala> def someFunction(a: A, newVal: Int): Unit = { a.m = newVal }
someFunction: (a: A, newVal: Int)Unit
scala> someFunction(a, 3)
scala> a.m
res2: Int = 3
Using mutable state like this is NOT recommended. This example is just for illustration purposes. In this case you pass a copy of object reference a
from which you can access the field directly and modify it.
If you want to understand this better read up on passing by value and passing by reference. Contrast C/C++ pointer and by reference args with Java and Scala. One difference between Scala and Java here is that in Java everything is a var
by default, so if you write your arg as final num
in Java it will also fail compilation and will work similarly to Scala in this case.
Upvotes: 2
Reputation: 49705
Because the JVM uses call-by-value semantics, and because Int is a primitive type (not an object reference).
What this means is that num
inside the method is not the same as num
on the outside, the only thing passed to the method is 1
It's a good thing too... It's bad enough when you have a mutable object and some innocent-looking method goes and changes things around behind your back. I don't wish to imagine the new category of bugs that would emerge if the same risk also existed for simple numbers!
Upvotes: 2
Reputation: 5585
@flavian's link answers the "why not" part, but here's how you do what you're trying to do. Make someFunction
a function instead of a procedure.
var num = 1
def someFunction(num: Int) = num + 1
num = someFunction(num)
Note though that this isn't idiomatic scala. Avoid using var
s whenever you can for best style.
Or alternatively for even worse style (seriously, this works, but don't ever do it):
var num = 1
def someFunction() = num += 1
someFunction()
print(num)
Upvotes: 0