Why is the splat/unary operator changing the assigned value a when p is called before *a = ""?
ruby
Solution
Very interesting question! Ruby takes this expression:
p *a = "a"
and translates it to something like this:
temp = (a = "a")
p *temp
So the first thing that happens is that `a` gets assigned to `"a"`, and then the result of the assignment expression which is `"a"` gets splatted and sent to `p`. Since `p`'s default behaviour when sent multiple arguments is just to iterate over and print each one, you only see `"a"` appear.
In short, it follows a "assign then splat" order of evaluation. So `a` gets assigned to `"a"` before the string gets splatted.
When you don't have a function call however, it is interpreted as something like this:
# *a = "a" gets interpreted as:
temp = "a"
a = *temp
This follows a "splat then assign" order of evaluation. So `a` gets assigned after the string gets splatted.
You can see what's being received by a function by going like this:
def foo *args
puts args.inspect
end
foo *a = "a" # outputs ["a"]
a # outputs "a"
Hope this clears up what's going on!
In short (thanks to Mark Reed):
p *a = "a" # interpreted as: p(*(a = "a"))
*a = "a" # interpreted as: a = *("a")
Problem
To give a little context around how I understand the problem. Using splat collect on a string sends :to_a or :to_ary to the String ``` class String def method_missing method, *args, &block p method #=> :to_ary p args #=> [] p block #=> nil end end *b = "b" ``` So I was thinking that redefining the :to_ary method would be what I'm after. ``` class String def to_ary ["to_a"] end end p *a = "a" #=> "a" p a #=> "a" *b = "b" p b #=> ["to_a"] ``` Now this confuses me to no end. Printing the result from the *a = "a" changes the value assigned to a? To demonstrate further ``` class String def to_ary [self.upcase!] end end p *a = "a" #=> "a" p a #=> "a" *b = "b" p b #=> ["B"] ```