J
Jörg W Mittag
Hi!
According to the specification,
primary_expression[indexing_argument_list] ω= expression
is (roughly) evaluated like
o = primary_expression
*l = indexing_argument_list
v = o.[](*l)
w = expression
(v ω w).tap {|x|
l << x
o.[]=(*l)
}
In particular, this means that the assignment *always* takes place.
However, at least in some Ruby implementations (I tested MRI, YARV,
Rubinius, JRuby and IronRuby), this doesn't actually seem to be the
case, at least for some operators:
def (h = {int: 0}).[]=(k, v) p "Setting #{k} to #{v}"; super end
h[:int] += 1
# "Setting int to 1"
h[:int] += 1
# "Setting int to 2"
This calls the setter twice, as expected per the specification.
h[:key] ||= :value
# "Setting key to value"
h[:key] ||= :value
But this doesn't.
Since the purpose of the specification is to describe the currently
existing implementations, this is obviously a bug in the specification
rather than a bug in all five currently released implementations,
especially since there is a ton of code and even a common idiom that
depends on the current behavior. But what would the correct
specification look like?
Thanks in advance,
Jörg.
According to the specification,
primary_expression[indexing_argument_list] ω= expression
is (roughly) evaluated like
o = primary_expression
*l = indexing_argument_list
v = o.[](*l)
w = expression
(v ω w).tap {|x|
l << x
o.[]=(*l)
}
In particular, this means that the assignment *always* takes place.
However, at least in some Ruby implementations (I tested MRI, YARV,
Rubinius, JRuby and IronRuby), this doesn't actually seem to be the
case, at least for some operators:
def (h = {int: 0}).[]=(k, v) p "Setting #{k} to #{v}"; super end
h[:int] += 1
# "Setting int to 1"
h[:int] += 1
# "Setting int to 2"
This calls the setter twice, as expected per the specification.
h[:key] ||= :value
# "Setting key to value"
h[:key] ||= :value
But this doesn't.
Since the purpose of the specification is to describe the currently
existing implementations, this is obviously a bug in the specification
rather than a bug in all five currently released implementations,
especially since there is a ton of code and even a common idiom that
depends on the current behavior. But what would the correct
specification look like?
Thanks in advance,
Jörg.