I found it to be confusing how method chaining works on mutable struct.
If you have code like this:
struct MyStruct def initialize(@a = 0) end def plus_1 @a += 1 self end def to_s(io) io << @a end end a = MyStruct.new printf "result of a.plus_1 = %s, after that a = %s\n", a.plus_1, a printf "result of a.plus_1.plus_1 = %s, after that a = %s\n", a.plus_1.plus_1, a
It gives you the result:
result of a.plus_1 = 1, after that a = 1 result of a.plus_1.plus_1 = 3, after that a = 2
That looks like the first method call acts on the stuct itself, but the second call acts on the copy of the result of the first call. Therefore the struct value gets modified by the first call, but the second call modifies only the copy that is discarded after printing.
That looks strange. I would think that calling the method on the object is not the same as passing the object as a parameter to any function. When passing struct as a parameter, it is passed by value (copied), and that is fine. But when stuct is the receiver of the method, you don’t expect the receiver to be copied. And for the first call it is not. That’s fine. But for the second chained call this does not hold. And that is strange.
I would find it ok if the receiver be always copied. Then struct would be really immutable unless you explicitly assign it to itself. And then you would know that method calls just cannot modify the reciever “in place” as struct is Value and immutable.
Of course, this code works fine if you change struct to class. Then everything works without surprises as class is Reference and is passed by address.
Any comments on that, please?