From: Jörg W Mittag on 7 Jun 2010 11:42 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.
From: Rein Henrichs on 7 Jun 2010 13:04 On 2010-06-07 08:42:08 -0700, J�rg W Mittag said: > 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. It is commonly thought that x <operator>= y is exactly equivalent to x = x <operator> y in all cases. What you have just demonstrated is that, presumably for performance reasons, h[key] ||= value is in fact equivalent to h[key] || h[key] = value, rather than h[key] = h[key] || value. This prevents a second lookup in the case where k[key] exists and is not nil or false. As to what the correct specification would look like, I am not sure, but I do agree with you. -- Rein Henrichs http://puppetlabs.com http://reinh.com
From: Rick DeNatale on 7 Jun 2010 15:18 On Mon, Jun 7, 2010 at 1:05 PM, Rein Henrichs <reinh(a)reinh.com> wrote: > It is commonly thought that x <operator>= y is exactly equivalent to x = x > <operator> y in all cases. What you have just demonstrated is that, > presumably for performance reasons, h[key] ||= value is in fact equivalent > to h[key] || h[key] = value, rather than h[key] = h[key] || value. This > prevents a second lookup in the case where k[key] exists and is not nil or > false. > x ||= y is NOT equivalent to x = x || y Instead a closer approximation is x || x = y http://talklikeaduck.denhaven2.com/2008/04/26/x-y-redux -- Rick DeNatale Blog: http://talklikeaduck.denhaven2.com/ Github: http://github.com/rubyredrick Twitter: @RickDeNatale WWR: http://www.workingwithrails.com/person/9021-rick-denatale LinkedIn: http://www.linkedin.com/in/rickdenatale
From: Rein Henrichs on 7 Jun 2010 16:25 On 2010-06-07 12:18:39 -0700, Rick DeNatale said: > On Mon, Jun 7, 2010 at 1:05 PM, Rein Henrichs <reinh(a)reinh.com> wrote: >> It is commonly thought that x <operator>= y is exactly equivalent to x = x >> <operator> y in all cases. What you have just demonstrated is that, >> presumably for performance reasons, h[key] ||= value is in fact equivalent >> to h[key] || h[key] = value, rather than h[key] = h[key] || value. This >> prevents a second lookup in the case where k[key] exists and is not nil or >> false. >> > > x ||= y is NOT equivalent to x = x || y > > Instead a closer approximation is > > x || x = y > > http://talklikeaduck.denhaven2.com/2008/04/26/x-y-redux Good explanation in that post, Rick. Thanks! -- Rein Henrichs http://puppetlabs.com http://reinh.com
|
Pages: 1 Prev: Final RubyInstaller packages released! Next: Complex numbers contradiction? |