This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
++ operator in Scala
I want to increment an Int variable in scala. But, because Int is immutable, I have to do this
var myInt: Int = 5
....
myInt = myInt + 1
which seems a little too complicated. What I would like to do is
var myInt: Int = 5
....
myInt++
however, since Int is immutable, I can't do this. Is there any solution? Because I can't be first who would want to use ++ on integer variable...
A ++ operator is not a language construct of Scala, and the desired behaviour cannot be achieved with a regular method definition. But Scala offers at least some syntactic help, in that a call a += b will be automatically expanded to a = a + b unless a direct method += exists. Thus:
var myInt = 5
myInt += 1
Related
Just starting out with Scala
var c = 0
c += 1 works
c.+= gives me error: value += is not a member of Int
Where is the += defined?
Section 6.12.4 Assignment Operators of the Scala Language Specification (SLS) explains how such compound assignment operators are desugared:
l ω= r
(where ω is any sequence of operator characters other than <, >, ! and doesn't start with =) gets desugared to
l.ω=(r)
IFF l has a member named ω= or is implicitly convertible to an object that has a member named ω=.
Otherwise, it gets desugared to
l = l.ω(r)
(except l is guaranteed to be only evaluated once), if that typechecks.
Or, to put it more simply: the compiler will first try l.ω=(r) and if that doesn't work, it will try l = l.ω(r).
This allows something like += to work like it does in other languages but still be overridden to do something different.
Actually, the code you've described does work.
scala> var c = 4
c: Int = 4
scala> c.+=(2) // no output because assignment is not an expression
scala> c
res1: Int = 6
I suspect (but can't say for sure) that it can't be found in the library because the compiler de-surgars (rewrites) it to c = c.+(1), which is in the library.
This question already has answers here:
toList on Range with suffix notation causes type mismatch
(2 answers)
Closed 6 years ago.
Here is the code that compiles as intended
def coarse_grained: Int = {
def fib: Int = List(1,2) sum ;
fib
}
and one which does not
def coarse_grained: Int = {
def fib: Int = List(1,2) sum
fib
}
The only difference is ; after the sum.
As you know, List(2,6,9).drop(1) can also be written as List(2,6,9) drop 1. In fact, it can also be written like this.
List(2,6,9) drop
1
The compiler keeps looking for the final argument, even past a newline. So if you want to do this List(1,2).sum like this List(1,2) sum, you'll need to use the semicolon ; to tell the compiler to stop looking for the final argument. It's not coming.
Simple scala question. Consider the below.
scala> var mycounter: Int = 0;
mycounter: Int = 0
scala> mycounter += 1
scala> mycounter
res1: Int = 1
In the second statement I increment my counter. But nothing is returned. How do I increment and return something in one statement.
Using '+=' return Unit, so you should do:
{ mycounter += 1; mycounter }
You can too do the trick using a closure (as function parameters are val):
scala> var x = 1
x: Int = 1
scala> def f(y: Int) = { x += y; x}
f: (y: Int)Int
scala> f(1)
res5: Int = 2
scala> f(5)
res6: Int = 7
scala> x
res7: Int = 7
BTW, you might consider using an immutable value instead, and embrace this programming style, then all your statements will return something ;)
Sometimes I do this:
val nextId = { var i = 0; () => { i += 1; i} }
println(nextId()) //> 1
println(nextId()) //> 2
Might not work for you if you need sometime to access the value without incrementing.
Assignment is an expression that is evaluated to Unit. Reasoning behind it can be found here: What is the motivation for Scala assignment evaluating to Unit rather than the value assigned?
In Scala this is usually not a problem because there probably is a different construct for the problem you are solving.
I don't know your exact use case, but if you want to use the incrementation it might be in the following form:
(1 to 10).foreach { i =>
// do something with i
}
I mean, I know what it means: take the list and add 1 to each element in it; that is, it's equivalent to map (1 + _ ). What I don't understand is how Scala knows it's equivalent. What's going on here?
Edit
Daniel points out it's a more general question. For example
def g(f : Int => Int, x : Int) = f(f(x))
g( (1 + ), 2)
res12: Int = 4
Which is cool. Every day I find a new useful thing that Scala can do. I guess what I'm looking for a full description (and ideally a name) of this particular thing.
It goes a bit like this:
map expects a function Int => B (in this case).
1 + doesn't resolve to a function Int => B, so try other things.
1 + can be lifted from a method expecting an Int parameter to a function Int => Int.
Presto.
One uses 1 + _ to solve ambiguity.
This simple test, of course, works as expected:
scala> var b = 2
b: Int = 2
scala> b += 1
scala> b
res3: Int = 3
Now I bring this into scope:
class A(var x: Int) { def +=(y:Int) { this.x += y } }
implicit def int2A(i:Int) : A = new A(i)
I'm defining a new class and a += operation on it, and a convenient implicit conversion for those times when I want to add an Int to A's Int value.
I never expected this would affect the way my regular Int operations behave, when the "A" class is not at all part of the expression.
But it does:
scala> var b:Int = 0
b: Int = 0
scala> b += 1
scala> b
res29: Int = 0
scala> b += 2
scala> b
res31: Int = 0
What seems to be happening here is that the b:Int is implicitly converted to an "A", which is not bound to any variable, and then += is invoked on it, discarding the results.
Scala seems to give high precedence the implicit conversion over the natural += behavior (compiler magic, not an actual method) that is already defined to Ints. Common-sense as well as a C++ background tells me implicits should only be invoked as a last resort, when the compilation would otherwise fail. That leads to several questions...
Why? Is this a bug? Is it by design?
Is there a work-around (other than not using "+=" for my DSL's "+=" operation)?
Thanks
As others have noted, Int cannot have a += "method", because Int is immutable. What happens instead is that x += 1 is treated as a short form for x = x + 1, but only if there is no
method called += that is defined on the type. So method resolution takes precedence.
Given that Scala lets you define += methods and also lets you do += on variables, could we have changed the priority of the two? I.e. try expanded += first and only if that fails search for a method named +=?
Theoretically yes, but I argue it would have been worse than the current scheme. Practically, no. There are many types in Scala's collection library that define both a + method for
non-destructive addition and a += method for destructive addition. If we had switched the priority around then a call like
myHashTable += elem
would expand to
myHashTable = myHashTable + elem
So it would construct a new hashtable and assign this back to the variable, instead of simply updating an element. Not a wise thing to do...
From Programming in Scala, Chapter 17:
Whenever you write a += b, and a does
not support a method named +=, Scala
will try interpreting it as a = a + b.
The class Int does not contain method +=. However class A provides += method. That might be triggering the implicit conversion from Int to A.
I don't think it is a bug.
Actually, Int only has a "+" method but doesn't have a "+=" method.
b += 1 would transform to b = b + 1 in compile time if there is not a other implicit which has a "+=" method exists.
Scala seems to give high precedence the implicit conversion over the natural += that is already defined to Ints.
Which version of Scala are you talking about? I don't know of any version that has a += method on Int. Certainly, none of the still supported versions do, that must be some really ancient version you have there.
And since there is no += on Int, but you are calling a += method on Int, Scala tries to satisfy that type constraint via an implicit conversion.
Even withstanding Eastsun's explanation, it seems like this is a bug, and it should try the b=b+1 transformation before trying an implicit conversion for +=.
Please ask this question to the scala-user email list by emailing scala-user#listes.epfl.ch or by visiting n4.nabble.com/Scala-User-f1934582.html. If it's a bug, that's where it will be noticed and fixed.