I am reading some of the ruby files in rails and I an seeing the ||= method used a lot. knowing ruby the way I do, I realize that she has lots of magical surprises and I really want to get to know this girl!
(OK, so one iddy bitty part of this is a rails question, and dangit, this is a ruby forum, but you guys are smarter and have better haircuts)
Question (1) After several hours of searching I find virtually nothing that fully explains the line @singular ||= options[:singular] || plural.to_s.singularize
I think know what is does, It assigns @singular a value for a "singular named" controller if the options hash contains the symbol :singular. I am looking more for a full description of how ||= and it's friends like &&= actually work.
my current understanding shows me: @singular = (options[:singular]) or (plural.to_s.singularize)
but the full logic seems to be more like: if options contains a symbol named :singular then @singular = plural.to_s.singularize end if
But what is the value of @singular if there is no :singular symbol? nil?
What I think is going on is a lot more like an IF statement than a OR statement.
Question (2) in the line: @plural ||= entities if entities is (false?, nil? something that fails "OR") what happens to @plural?
Once again, the ||= seems more like an "equals If" statement rather than an "equals Or" statement.
Question (3) @path_segment = options.delete(:as) || @plural So @path_segment is assigned either the return from the delete operation (:as) ? or the plural name of the controller. Is that correct? Where in a common resourceful routes mapping is there an :as?
@plural||=entries simply says, if @plural is nil or false (someone correct me if I'm a tad off), set it to entries, otherwise don't do anything.
For @singular, close but.. you need the or @singular ||= ((options[:singular]) or (plural.to_s.singularize))
@path_segment is a little bit stranger, but for me it harkens back to c days. if options.delete(:as) returns any value that evalutes to true (anything but nil or false), @path_segment is set to that value. If options.delete(:as) fails or returns nil, @path_segment is set to @plural.
On Thu, May 1, 2008 at 11:20 AM, Ruby Freak <twscann...@gmail.com> wrote: > I am reading some of the ruby files in rails and I an seeing the ||= > method used a lot. > knowing ruby the way I do, I realize that she has lots of magical > surprises and I really want to get to know this girl!
> (OK, so one iddy bitty part of this is a rails question, and dangit, > this is a ruby forum, but you guys are smarter and have better > haircuts)
> Question (1) > After several hours of searching I find virtually nothing that fully > explains the line > @singular ||= options[:singular] || plural.to_s.singularize
> I think know what is does, It assigns @singular a value for a > "singular named" controller if the options hash contains the > symbol :singular. I am looking more for a full description of how ||= > and it's friends like &&= actually work.
> my current understanding shows me: > @singular = (options[:singular]) or (plural.to_s.singularize)
> but the full logic seems to be more like: > if options contains a symbol named :singular then > @singular = plural.to_s.singularize > end if
> But what is the value of @singular if there is no :singular symbol? > nil?
> What I think is going on is a lot more like an IF statement than a OR > statement.
> Question (2) > in the line: @plural ||= entities > if entities is (false?, nil? something that fails "OR") what happens > to @plural?
> Once again, the ||= seems more like an "equals If" statement rather > than an "equals Or" statement.
> Question (3) > @path_segment = options.delete(:as) || @plural > So @path_segment is assigned either the return from the delete > operation (:as) ? or the plural name of the controller. Is that > correct? Where in a common resourceful routes mapping is there an :as?
On Fri, 2 May 2008, Ruby Freak wrote: > I am reading some of the ruby files in rails and I an seeing the ||= > method used a lot. > knowing ruby the way I do, I realize that she has lots of magical > surprises and I really want to get to know this girl!
x ||= y means: x || x = y
The difference is that x ||= y won't complain if x is undefined, whereas if you type x || x = y and there's no x in scope, it will. The basic idea is that if x is (a) undefined (b) nil (c) false, you want to set it to y. Otherwise, you want to leave it alone. The whole expression evaluates to x, after the assignment has happened (or not).
-- Rails training from David A. Black and Ruby Power and Light: INTRO TO RAILS June 9-12 Berlin ADVANCING WITH RAILS June 16-19 Berlin INTRO TO RAILS June 24-27 London (Skills Matter) See http://www.rubypal.com for details and updates!
* David A. Black <dbl...@rubypal.com> (18:56) schrieb:
> Hi --
> On Fri, 2 May 2008, Ruby Freak wrote:
>> I am reading some of the ruby files in rails and I an seeing the ||= >> method used a lot. >> knowing ruby the way I do, I realize that she has lots of magical >> surprises and I really want to get to know this girl!
> x ||= y means: x || x = y
No, it means: x = x || y
> The difference is that x ||= y won't complain if x is undefined,
> * David A. Black <dbl...@rubypal.com> (18:56) schrieb:
>> Hi --
>> On Fri, 2 May 2008, Ruby Freak wrote:
>>> I am reading some of the ruby files in rails and I an seeing the ||= >>> method used a lot. >>> knowing ruby the way I do, I realize that she has lots of magical >>> surprises and I really want to get to know this girl! >> x ||= y means: x || x = y
On Fri, 2 May 2008, Simon Krahnke wrote: > * David A. Black <dbl...@rubypal.com> (18:56) schrieb:
>> Hi --
>> On Fri, 2 May 2008, Ruby Freak wrote:
>>> I am reading some of the ruby files in rails and I an seeing the ||= >>> method used a lot. >>> knowing ruby the way I do, I realize that she has lots of magical >>> surprises and I really want to get to know this girl!
>> x ||= y means: x || x = y
> No, it means: x = x || y
This is becoming a bit of a perma-thread :-)
See Robert K.'s answer, and also have a look at the blog post I mentioned in my response. It's about exactly why x = x || y is not the right expansion for x ||= y.
David
-- Rails training from David A. Black and Ruby Power and Light: INTRO TO RAILS June 9-12 Berlin ADVANCING WITH RAILS June 16-19 Berlin INTRO TO RAILS June 24-27 London (Skills Matter) See http://www.rubypal.com for details and updates!
| On 01.05.2008 20:54, Simon Krahnke wrote: |> * David A. Black <dbl...@rubypal.com> (18:56) schrieb: |> |>> Hi -- |>> |>> On Fri, 2 May 2008, Ruby Freak wrote: |>> |>>> I am reading some of the ruby files in rails and I an seeing the ||= |>>> method used a lot. |>>> knowing ruby the way I do, I realize that she has lots of magical |>>> surprises and I really want to get to know this girl! |>> x ||= y means: x || x = y |> |> No, it means: x = x || y | | I believe you are wrong. | | irb(main):001:0> h={} | => {} | irb(main):002:0> h=Hash.new true | => {} | irb(main):003:0> h[1] | => true | irb(main):004:0> h[1] ||= 10 | => true | irb(main):005:0> h | => {} | irb(main):006:0> | | If you were right, h would look differently: | | irb(main):008:0> h=Hash.new true | => {} | irb(main):009:0> h[1] = h[1] || 10 | => true | irb(main):010:0> h | => {1=>true} | | The same topic has been discussed exhaustively a few days ago. | | Cheers | | robert | |
You are wrong, too, though.
I refer you to Ruby-Talk 297145[0]:
Quoth Joshua Ballanco: 'The only reason that Chris' example behaves like "x || x = stuff" is because he's defined a default value for the hash. If you set a default value, than you'll never have a keyed value be empty (i.e. nil). '
x = x || 'a value' works when x is nil or false. Once the Hash has a default value, it shouldn't be false, much less nil.
~ Calvin: I'm a genius, but I'm a misunderstood genius. Hobbes: What's misunderstood about you? Calvin: Nobody thinks I'm a genius. -- Calvin -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.8 (MingW32) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org
|> No, it means: x = x || y | | This is becoming a bit of a perma-thread :-) | | See Robert K.'s answer, and also have a look at the blog post I | mentioned in my response. It's about exactly why x = x || y is not the | right expansion for x ||= y.
x ||= y expands into x = x || y, since x == 1 expands to x = x + 1, and we have no reason to expect ||= to behave differently (MPLOS).
Also, it works as expected if the expansion x = x || y is correct. After all:
'The or and || operators evaluate their first operand. If true, the expression returns the value of their first operand; otherwise, the expression returns the value of the second operand.' Programming Ruby, 2nd Edition (p. 326).
And Robert's answer works the way it works because the Hash has a default value set, which doesn't equate to false or nil. If you override the default value by setting the value to false, the assignment works again as expected.
Zero raised to the nth power remains zero. ~ -- Pop Baslim -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.8 (MingW32) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org
On Fri, 2 May 2008, Phillip Gawlowski wrote: > -----BEGIN PGP SIGNED MESSAGE----- > Hash: SHA1
> Robert Klemme wrote: > | On 01.05.2008 20:54, Simon Krahnke wrote: > |> * David A. Black <dbl...@rubypal.com> (18:56) schrieb: > |> > |>> Hi -- > |>> > |>> On Fri, 2 May 2008, Ruby Freak wrote: > |>> > |>>> I am reading some of the ruby files in rails and I an seeing the ||= > |>>> method used a lot. > |>>> knowing ruby the way I do, I realize that she has lots of magical > |>>> surprises and I really want to get to know this girl! > |>> x ||= y means: x || x = y > |> > |> No, it means: x = x || y > | > | I believe you are wrong. > | > | irb(main):001:0> h={} > | => {} > | irb(main):002:0> h=Hash.new true > | => {} > | irb(main):003:0> h[1] > | => true > | irb(main):004:0> h[1] ||= 10 > | => true > | irb(main):005:0> h > | => {} > | irb(main):006:0> > | > | If you were right, h would look differently: > | > | irb(main):008:0> h=Hash.new true > | => {} > | irb(main):009:0> h[1] = h[1] || 10 > | => true > | irb(main):010:0> h > | => {1=>true} > | > | The same topic has been discussed exhaustively a few days ago. > | > | Cheers > | > | robert > | > |
> You are wrong, too, though.
> I refer you to Ruby-Talk 297145[0]:
> Quoth Joshua Ballanco: > 'The only reason that Chris' example behaves like "x || x = stuff" is > because he's defined a default value for the hash. If you set a default > value, than you'll never have a keyed value be empty (i.e. nil). '
> x = x || 'a value' works when x is nil or false. Once the Hash has a > default value, it shouldn't be false, much less nil.
The question, though, is what x ||= y expands to. Robert's point is that if you say it expands to x = x || y, that doesn't account for what happens with a hash that has a non-false default value.
Mind you, x || x = y doesn't account (as I mentioned) for the fact that if x isn't defined, you can't use that syntax. x ||= y is really its own thing, and doesn't expand 100% of the time to anything. But x || x = y, if you allow for the undefined x thing, describes all of the behaviors, including the hash edge case.
David
-- Rails training from David A. Black and Ruby Power and Light: INTRO TO RAILS June 9-12 Berlin ADVANCING WITH RAILS June 16-19 Berlin INTRO TO RAILS June 24-27 London (Skills Matter) See http://www.rubypal.com for details and updates!
On Fri, 2 May 2008, Phillip Gawlowski wrote: > -----BEGIN PGP SIGNED MESSAGE----- > Hash: SHA1
> David A. Black wrote:
> |> No, it means: x = x || y > | > | This is becoming a bit of a perma-thread :-) > | > | See Robert K.'s answer, and also have a look at the blog post I > | mentioned in my response. It's about exactly why x = x || y is not the > | right expansion for x ||= y.
> x ||= y expands into x = x || y, since x == 1 expands to x = x + 1, and
I think you mean +=.
> we have no reason to expect ||= to behave differently (MPLOS).
That's really where this thread always starts, though: why doesn't it behave like x = x || y in every case? Anyway, the thing about MPOLS is that you and I can't invoke it :-) It was actually Matz who showed me the x || x = y expansion (most recently at EuRuKo, where I talked to him about it because I wanted to make sure the corrections I made to my blog post had made it correct).
> Also, it works as expected if the expansion x = x || y is correct. After > all:
> 'The or and || operators evaluate their first operand. If true, the > expression returns the value of their first operand; otherwise, the > expression returns the value of the second operand.' > Programming Ruby, 2nd Edition (p. 326).
> And Robert's answer works the way it works because the Hash has a > default value set, which doesn't equate to false or nil. If you override > the default value by setting the value to false, the assignment works > again as expected.
Right, but hashes are allowed to have default values. So an explanation that accounts for that case is better than one that doesn't. The point is that if you do a drop-in replacement x = x || y you get a different result from ||=, and with x || x = y you don't. That means, definitively I think, that the latter is a more correct expansion. (I'm not sure how it couldn't mean that.)
Anyway, this is at least the third thread on this in recent months, and I've written my blog post (and correction follow-up :-) about it. I think I'm about ||='d out.
David
-- Rails training from David A. Black and Ruby Power and Light: INTRO TO RAILS June 9-12 Berlin ADVANCING WITH RAILS June 16-19 Berlin INTRO TO RAILS June 24-27 London (Skills Matter) See http://www.rubypal.com for details and updates!
|> x ||= y expands into x = x || y, since x == 1 expands to x = x + 1, and | | I think you mean +=.
Yes, indeed.
|> we have no reason to expect ||= to behave differently (MPLOS). | | That's really where this thread always starts, though: why doesn't it | behave like x = x || y in every case? Anyway, the thing about MPOLS is | that you and I can't invoke it :-) It was actually Matz who showed me | the x || x = y expansion (most recently at EuRuKo, where I talked to | him about it because I wanted to make sure the corrections I made to | my blog post had made it correct).
It doesn't behave that way because classes can implement and override behavior. Which can lead to surprising results, and sometimes pathological cases of Monkeypatching. ;)
Also, the MPLOS helps as a guideline, not as a hard and fast rule. :)
|> And Robert's answer works the way it works because the Hash has a |> default value set, which doesn't equate to false or nil. If you override |> the default value by setting the value to false, the assignment works |> again as expected. | | Right, but hashes are allowed to have default values. So an | explanation that accounts for that case is better than one that | doesn't. The point is that if you do a drop-in replacement x = x || y | you get a different result from ||=, and with x || x = y you don't. | That means, definitively I think, that the latter is a more correct | expansion. (I'm not sure how it couldn't mean that.)
However, a default value results in the Hash not evaluating to nil or false. Which is required for || and OR to use their *second* operand (since it otherwise uses the first operand), so x || x = y cannot work. Unless we get into precedence issues here, I guess.
| Anyway, this is at least the third thread on this in recent months, | and I've written my blog post (and correction follow-up :-) about it. | I think I'm about ||='d out.
~ Why do we drink cow's milk? Who was the first guy who first looked at a cow and said "I think I'll drink whatever comes out of these things when I squeeze 'em!"? -- Calvin -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.8 (MingW32) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org
On Fri, 2 May 2008, Phillip Gawlowski wrote: > However, a default value results in the Hash not evaluating to nil or > false. Which is required for || and OR to use their *second* operand > (since it otherwise uses the first operand), so x || x = y cannot work. > Unless we get into precedence issues here, I guess.
It depends what you mean by work :-) See Robert's example.
> | Anyway, this is at least the third thread on this in recent months, > | and I've written my blog post (and correction follow-up :-) about it. > | I think I'm about ||='d out.
> So am I.
Whoops -- sorry :-)
I actually have a feeling we're talking at cross-purposes, and that I'm somehow not getting something. All I'm saying is that h[x] ||= value is the same as h[x] || h[x] = value, for any hash h and any key x. That can be demonstrated easily (as Robert did) just by substituting one expression for the other. It's an unusual case, but it's legal. I'm not sure what would be needed beyond that to demonstrate that x = x || y is not a drop-in replacement for x ||= y.
David
-- Rails training from David A. Black and Ruby Power and Light: INTRO TO RAILS June 9-12 Berlin ADVANCING WITH RAILS June 16-19 Berlin INTRO TO RAILS June 24-27 London (Skills Matter) See http://www.rubypal.com for details and updates!
| Hi -- | | On Fri, 2 May 2008, Phillip Gawlowski wrote: | | Whoops -- sorry :-)
As if. :P
| I actually have a feeling we're talking at cross-purposes, and that | I'm somehow not getting something. All I'm saying is that h[x] ||= | value is the same as h[x] || h[x] = value, for any hash h and any key | x. That can be demonstrated easily (as Robert did) just by | substituting one expression for the other. It's an unusual case, but | it's legal. I'm not sure what would be needed beyond that to | demonstrate that x = x || y is not a drop-in replacement for x ||= y.
Yeah, I'm taking the Bird's Eye View on it all, essentially saying: 'it works like this almost always, but Hash is a special case, since it has default values [or whatever the implementation detail is, that makes Hash work differently]).
~ "Endorsing products is the American way of expressing individuality." - -Calvin -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.8 (MingW32) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org
On Fri, 2 May 2008, Phillip Gawlowski wrote: > -----BEGIN PGP SIGNED MESSAGE----- > Hash: SHA1
> David A. Black wrote: > | Hi -- > | > | On Fri, 2 May 2008, Phillip Gawlowski wrote: > | > | Whoops -- sorry :-)
> As if. :P
> | I actually have a feeling we're talking at cross-purposes, and that > | I'm somehow not getting something. All I'm saying is that h[x] ||= > | value is the same as h[x] || h[x] = value, for any hash h and any key > | x. That can be demonstrated easily (as Robert did) just by > | substituting one expression for the other. It's an unusual case, but > | it's legal. I'm not sure what would be needed beyond that to > | demonstrate that x = x || y is not a drop-in replacement for x ||= y.
> Yeah, I'm taking the Bird's Eye View on it all, essentially saying: 'it > works like this almost always, but Hash is a special case, since it has > default values [or whatever the implementation detail is, that makes > Hash work differently]).
It's possible to generalize it; someone in one of the threads wrote a class that showed the same behavior, but I can't remember the details. I do wish it were otherwise; it's definitely unexpected, I think.
David
-- Rails training from David A. Black and Ruby Power and Light: INTRO TO RAILS June 9-12 Berlin ADVANCING WITH RAILS June 16-19 Berlin INTRO TO RAILS June 24-27 London (Skills Matter) See http://www.rubypal.com for details and updates!
| Hi -- | | It's possible to generalize it; someone in one of the threads wrote a | class that showed the same behavior, but I can't remember the details. | I do wish it were otherwise; it's definitely unexpected, I think.
Well, it is unexpected if you forget about the default value for Hash, for example.
So, I agree: On first sight it *is* unintuitive. Once you think about, though..
As a tangent: I've just checked my copy of The Ruby Way, and its 'Training your intuition' sub-chapter. This gotcha isn't part of it. :(
Maybe it could be added for the next edition (unless Ruby 1.9/2.0 is the reason for the new edition, and the ambiguity/idiosyncrasy is removed in the new version of Ruby by then).
~ "Oops, I always forget the purpose of competition is to divide people into winners and losers." -Hobbes being sarcastic -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.8 (MingW32) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org
> I am reading some of the ruby files in rails and I an seeing the ||= > method used a lot. > knowing ruby the way I do, I realize that she has lots of magical > surprises and I really want to get to know this girl!
> (OK, so one iddy bitty part of this is a rails question, and dangit, > this is a ruby forum, but you guys are smarter and have better > haircuts)
> Question (1) > After several hours of searching I find virtually nothing that fully > explains the line > @singular ||= options[:singular] || plural.to_s.singularize
> I think know what is does, It assigns @singular a value for a > "singular named" controller if the options hash contains the > symbol :singular. I am looking more for a full description of how ||= > and it's friends like &&= actually work.
> my current understanding shows me: > @singular = (options[:singular]) or (plural.to_s.singularize)
> but the full logic seems to be more like: > if options contains a symbol named :singular then > @singular = plural.to_s.singularize > end if
> But what is the value of @singular if there is no :singular symbol? > nil?
> What I think is going on is a lot more like an IF statement than a OR > statement.
> Question (2) > in the line: @plural ||= entities > if entities is (false?, nil? something that fails "OR") what happens > to @plural?
> Once again, the ||= seems more like an "equals If" statement rather > than an "equals Or" statement.
> Question (3) > @path_segment = options.delete(:as) || @plural > So @path_segment is assigned either the return from the delete > operation (:as) ? or the plural name of the controller. Is that > correct? Where in a common resourceful routes mapping is there an :as?
> Thanks in advance for any help.
-- Kazuo Ishii Ph.D., Tokyo Univ. of Science freepar...@gmail.com
David A. Black wrote: > It's possible to generalize it; someone in one of the threads wrote a > class that showed the same behavior, but I can't remember the details.
In writing this article, I pulled my old dusty copy of Kernighan and Ritchie off my shelf, since IIRc the whole
x op= y
idea originally came from C.
And of course that's where the oft reported meme that
x op=y
was identical to
x = x op y
originated, and was propagated through several popular expositions of Ruby.
BUT
C, although it does have || and && as short-circuit boolean operators, does NOT allow ||= or &&=
When Matz added these to Ruby he, quite cleverly IMHO, defined them as short circuiting as well, the assignment is NOT done if the LHS evaluates to true (in the Ruby sense that is, neither nil nor false).
And as I also verified, since reading about ||= in David Flanigan's "The Ruby Programming Language" got me to thinking about it, &&= also doesn't do an assignment if the LHS evaluates to false.
All of this falls out naturally from 1) short-circuit evaluation of || and &&, and 2) the fact that a.x = y is syntactic sugar for a.x=(y), and 3) a[b] = c is syntactic sugar for a.[]=(b,c).
So a foolish adherence to the idea that Ruby should slavishly follow C where ||= and &&= are not allowable assignment operators, and there are no x= or []= methods to serve as targets of syntactic sugar, doesnt make that sense.
So:
1) In Ruby x ||= y does no assignment if x evaluates to true, and x &&= y does no assignment if x evaluates to true. 2) x || x = y, and x && x = y are much better first approximations of how x ||= y and x &&= y than x = x || y, and x = x && y, despite what K&R say. 3) I say first approximations because of David Black's observation that x ||= y and x || x = y differ when x is undefined.
In summary:
That's the way that Ruby works. Ruby ain't C, or C++ or Java.
> 1) In Ruby x ||= y does no assignment if x evaluates to true, and x > &&= y does no assignment if x evaluates to true. > 2) x || x = y, and x && x = y are much better first approximations of > how x ||= y and x &&= y than x = x || y, and x = x && y, despite what > K&R say. > 3) I say first approximations because of David Black's observation > that x ||= y and x || x = y differ when x is undefined.
> In summary:
> That's the way that Ruby works. Ruby ain't C, or C++ or Java.
Nice summary! And, if you think about it from a usability perspective it does make the most sense the way it is.
1. you do not want to spent CPU cycles for assigning the same object to a reference
2. more importantly, in the case of Hash you do not want the Hash to change (which it would do if ||= were implemented differently as I have demonstrated earlier).
I'm out.
Cheers
robert
-- use.inject do |as, often| as.you_can - without end
* Rick DeNatale <rick.denat...@gmail.com> (03:26) schrieb:
> 1) In Ruby x ||= y does no assignment if x evaluates to true, and x > &&= y does no assignment if x evaluates to true.
Eh, what? You are confusing me.
&&= does an assignment only if x evaluates to true.
The question of if there is an assignment in x = x is purely metaphysical: there is no way to tell.
> 2) x || x = y, and x && x = y are much better first approximations of > how x ||= y and x &&= y than x = x || y, and x = x && y, despite what > K&R say.
And doesn't explain why x springs into existence, if didn't exist before.
> 3) I say first approximations because of David Black's observation > that x ||= y and x || x = y differ when x is undefined.
Right, but x = x || y doesn't.
The only thing special about x ||= y is that x is only ever evaluated once. But that's special in every op=.
On Fri, May 2, 2008 at 8:35 AM, Simon Krahnke <overl...@gmx.li> wrote: > * Rick DeNatale <rick.denat...@gmail.com> (03:26) schrieb:
> > 1) In Ruby x ||= y does no assignment if x evaluates to true, and x > > &&= y does no assignment if x evaluates to true.
> Eh, what? You are confusing me.
> &&= does an assignment only if x evaluates to true.
Yes, that was a typo on my part, it should have read "and x &&= y does not assignment if x evaluates to false."
> The question of if there is an assignment in x = x is purely > metaphysical: there is no way to tell.
If x is a simple variable, that's correct, however if x is actually an "attribute accessor" like
foo.bar ||= y or foo[:bar] ||= y
Then you can tell if the bar= or []= method which gets invoked on 'assignment' has side effects.
> > 2) x || x = y, and x && x = y are much better first approximations of > > how x ||= y and x &&= y than x = x || y, and x = x && y, despite what > > K&R say.
> And doesn't explain why x springs into existence, if didn't exist > before.
This is because the Ruby parser recognizes the variable as local when it sees it as the POTENTIAL assignee. In the first chunk below, the a = 1 never got executed because of the if false modifier, but the parser still picked up a 'declaration' of a as a local variable.
defined? a # => nil a = 1 if false defined? a # => "local-variable" a # => nil
defined? b # => nil b ||= 1 defined? b # => "local-variable" b # => 1
defined? c # => nil c &&= 1 defined? c # => "local-variable" c # => nil
of course in the case of
d.e ||= g
or
h[1] ||= i
There's no question of the method 'springing' into existence, d.e, d.e=, h[], and h[]= will either work or throw a method not found if and when they are called.
> > 3) I say first approximations because of David Black's observation > > that x ||= y and x || x = y differ when x is undefined.
> Right, but x = x || y doesn't.
> The only thing special about x ||= y is that x is only ever evaluated > once. But that's special in every op=.
Except that, if x is really obj.foo, or obj[a] then the notion of x getting evaluated once is a little squirrelly, because reading x is done by evaluating obj.foo or obj.[](a), and writing it (should the assignment actually occur) is done by evaluating obj.foo=(y) or obj.[]=(a,y)
The fact that x = y is actually a method call under some circumstances is what's special about Ruby, and why simply extending K&Rs explanation of op= misses the point.