ruby - Why is the splat/unary operator changing the assigned value a when p is called before *a = ""? -
to give little context around how understand problem.
using splat collect on string sends :to_a or :to_ary string
class string def method_missing method, *args, &block p method #=> :to_ary p args #=> [] p block #=> nil end end *b = "b"
so thinking redefining :to_ary method i'm after.
class string def to_ary ["to_a"] end end p *a = "a" #=> "a" p #=> "a" *b = "b" p b #=> ["to_a"]
now confuses me no end.
printing result *a = "a" changes value assigned a?
to demonstrate further
class string def to_ary [self.upcase!] end end p *a = "a" #=> "a" p #=> "a" *b = "b" p b #=> ["b"]
very interesting question! ruby takes expression:
p *a = "a"
and translates this:
temp = (a = "a") p *temp
so first thing happens a
gets assigned "a"
, , result of assignment expression "a"
gets splatted , sent p
. since p
's default behaviour when sent multiple arguments iterate on , print each one, see "a"
appear.
in short, follows "assign splat" order of evaluation. a
gets assigned "a"
before string gets splatted.
when don't have function call however, interpreted this:
# *a = "a" gets interpreted as: temp = "a" = *temp
this follows "splat assign" order of evaluation. a
gets assigned after string gets splatted.
you can see what's being received function going this:
def foo *args puts args.inspect end foo *a = "a" # outputs ["a"] # outputs "a"
hope clears what's going on!
in short (thanks mark reed):
p *a = "a" # interpreted as: p(*(a = "a")) *a = "a" # interpreted as: = *("a")
Comments
Post a Comment