Re: Possible inconsistent error for "+=" shorthand while using immutable set

Andrew Phillips <[email protected]> Mon, 28 Mar 2016 11:27:00 -0700 (PDT)
Newsgroups gmane.comp.lang.scala
Message-ID <[email protected]>
*> The spec quote was taken backward: if x += y doesn't typecheck, then it 
tries x = x + y (if that type checks)*

Thanks for the correction, som-snytt! For completeness, here the relevant 
(hopefully not misleading) quote from the spec:

The re-interpretation occurs if the following *two* conditions are 
fulfilled.

   1. *The left-hand-side l does not have a member named +=*, and also 
   cannot be converted by an implicit conversion to a value with a member 
   named +=.
   2. The assignment l = l + r is type-correct. In particular this implies 
   that l refers to a variable or object that can be assigned to, and that is 
   convertible to a value with a member named +.
   
Regards

ap

On Monday, 28 March 2016 18:04:15 UTC+1, som-snytt wrote:
>
>
> The spec quote was taken backward: if x += y doesn't typecheck, then it 
> tries x = x + y (if that type checks). The quoted part also wrongly implies 
> that rewriting happens only when using infix syntax.
>
> I agree that the error messages could include what was tried (and maybe 
> how to fix it).
>
> scala> class C
> defined class C
>
> scala> var c = new C
> c: C = C@41a4555e
>
> scala> c += 1
> <console>:14: error: type mismatch;
>  found   : Int(1)
>  required: String
>        c += 1
>             ^
>
> scala> c.+=(1)
> <console>:14: error: type mismatch;
>  found   : Int(1)
>  required: String
>        c.+=(1)
>             ^
>
> scala> c.+=("1")
> <console>:14: error: type mismatch;
>  found   : String
>  required: C
>        c.+=("1")
>            ^
>
> scala> :replay -Yno-predef
> Replaying: class C
> defined class C
>
> Replaying: var c = new C
> c: C = C@3576ddc2
>
>
> scala> c += 1
> <console>:14: error: value + is not a member of C
>        c += 1
>          ^
>
> scala> c.+=(1)
> <console>:14: error: value + is not a member of C
>        c.+=(1)
>          ^
>
> scala> val c = new C
> c: C = C@495ee280
>
> scala> c.+=(1)
> <console>:14: error: value += is not a member of C
>        c.+=(1)
>          ^
>
>
> On Sunday, March 27, 2016 at 6:24:55 PM UTC-7, Christopher Lee wrote:
>>
>> Hey Andrew,
>>
>> Thanks for the clear explanation! The behavior makes sense to me now :)
>>
>> This might be crazy, but I wonder if it makes sense for immutable set to 
>> have a "+=" member (along with any other assignment operator) that throws a 
>> reassignment error.
>>
>> Thanks again,
>> Chris
>>
>> On Sunday, March 27, 2016 at 2:03:14 PM UTC-4, Andrew Phillips wrote:
>>>
>>> Hi Chris
>>>
>>> The behaviour you're seeing is indeed consistent with the language spec, 
>>> although I can imagine that it appears odd at first sight. In short, the 
>>> rewriting of a += b to a = a + b can only take place if a is something 
>>> "that can be assigned". Since that's not true for a val, the rewriting does 
>>> *not* take place, and so the compiler is forced to look for a member 
>>> "+=" on a instead. Since a in your example is an immutable set, it can't 
>>> find one (mutable sets *do* have a "+=" method [1]).
>>>
>>> Section 6.12.4 of the language spec [2] describes this in detail; here 
>>> an excerpt:
>>>
>>>
>>> Let’s consider an assignment operator such as += in an infix operation l 
>>> += r ,
>>> where l, r are expressions. This operation can be re-interpreted as an 
>>> operation
>>> which corresponds to the assignment
>>>
>>> l = l + r
>>>
>>> [...] if the following two conditions are fulfilled.
>>>
>>> [...]
>>>
>>> 2. The assignment l = l + r is type-correct. In particular this implies 
>>> that l
>>> refers to a variable or object that can be assigned to, and that is 
>>> convertible
>>> to a value with a member named +.
>>>
>>>
>>> Hope that helps!
>>>
>>> ap
>>>
>>> [1] 
>>> http://www.scala-lang.org/api/current/index.html#scala.collection.mutable.Set@+=(elem:A):SetLike.this.type
>>> [2] 
>>> http://www.scala-lang.org/files/archive/spec/2.11/06-expressions.html#assignment-operators
>>>
>>> On Sunday, 27 March 2016 18:11:00 UTC+1, Christopher Lee wrote:
>>>>
>>>> Hello,
>>>>
>>>> I'm just starting to learn Scala, and I came across the following 
>>>> example in the "Programming in Scala" book.
>>>>
>>>> var jetSet = Set("Boeing", "Airbus")
>>>> jetSet += "Lear"
>>>> println(jetSet.contains("Cessna"))
>>>>
>>>> One of the lesson points is that the default Set is immutable. So, I 
>>>> wanted to test that line 2 in the above actually reassigns a new immutable 
>>>> set with the element added to the jetSet variable.
>>>>
>>>> I then *changed the var to a val* and expected to see a reassignment 
>>>> error. Instead I got the below error.
>>>>
>>>> immutableSet.scala:2: error: value += is not a member of scala.
>>>> collection.immutable.Set[String]
>>>> jetSet += "Lear"
>>>>        ^
>>>>
>>>> While the error message is true, it's strange that the compiler didn't 
>>>> complain about "+=" before. "+=" is shorthand for `jetSet = jetSet + 
>>>> "Lear"`, so I would expect to see a reassignment error.
>>>>
>>>> E.g. If I were to run the program with the long form, I get the 
>>>> expected error message.
>>>>
>>>> val jetSet = Set("Boeing", "Airbus")
>>>> jetSet = jetSet + "Lear"
>>>> println(jetSet.contains("Cessna"))
>>>>
>>>> immutableSet.scala:2: error: reassignment to val
>>>> jetSet = jetSet + "Lear"
>>>>        ^
>>>>
>>>> Am I missing something (very likely since I'm a newb) or does this seem 
>>>> inconsistent?
>>>>
>>>> Thanks for reading!
>>>> Chris
>>>>
>>>

-- 
You received this message because you are subscribed to the Google Groups "scala-language" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [email protected].
For more options, visit https://groups.google.com/d/optout.