[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Please explain nuances of ||=

Ruby Freak

5/1/2008 4:16:00 PM

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!

Consider the initialize method of resources.rb

51 def initialize(entities, options)
52 @plural ||= entities
53 @singular ||= options[:singular] ||
plural.to_s.singularize
54 @path_segment = options.delete(:as) || @plural
55
56 @options = options
57
58 arrange_actions
59 add_default_actions
60 set_prefixes
61 end

(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.

27 Answers

Kyle Schmitt

5/1/2008 4:31:00 PM

0

You're close on some, right on some.

@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.

Does that help?
On Thu, May 1, 2008 at 11:20 AM, Ruby Freak <twscannell@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!
>
> Consider the initialize method of resources.rb
>
> 51 def initialize(entities, options)
> 52 @plural ||= entities
> 53 @singular ||= options[:singular] ||
> plural.to_s.singularize
> 54 @path_segment = options.delete(:as) || @plural
> 55
> 56 @options = options
> 57
> 58 arrange_actions
> 59 add_default_actions
> 60 set_prefixes
> 61 end
>
> (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.
>
>
>

Jeremy Henty

5/1/2008 4:32:00 PM

0

On 2008-05-01, Ruby Freak <twscannell@gmail.com> wrote:
> I am reading some of the ruby files in rails and I an seeing the ||=
> method used a lot.

There's a nice discussion at
<URL:http://talklikeaduck.denhaven2.com/articles/2008/04/26/x-y....

Regards,

Jeremy Henty

David A. Black

5/1/2008 4:56:00 PM

0

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

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).

See http://dablog.rubypal.com/2008/3/25/a-short-circuit... for
more.


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.r... for details and updates!

Ruby Freak

5/1/2008 5:05:00 PM

0



Yes, Thank you,

That is very helpful.

Google seems to puke on "||=" so I wasn't getting any search results.

Simon Krahnke

5/1/2008 6:55:00 PM

0

* David A. Black <dblack@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,

That's because = does the same.

mfg, simon .... l

Robert Klemme

5/1/2008 7:21:00 PM

0

On 01.05.2008 20:54, Simon Krahnke wrote:
> * David A. Black <dblack@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

David A. Black

5/1/2008 8:12:00 PM

0

Hi --

On Fri, 2 May 2008, Simon Krahnke wrote:

> * David A. Black <dblack@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.r... for details and updates!

Phillip Gawlowski

5/1/2008 8:25:00 PM

0

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Robert Klemme wrote:
| On 01.05.2008 20:54, Simon Krahnke wrote:
|> * David A. Black <dblack@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.

See:

irb(main):001:0> h = Hash.new
=> {}
irb(main):002:0> h[1].nil?
=> true
irb(main):003:0> h[1] = h[1] || 10
=> 10
irb(main):004:0> h[2] = 'not nil'
=> "not nil"
irb(main):005:0> h[2] = h[2] || 'a value'
=> "not nil"
irb(main):006:0> h[3] = false
=> false
irb(main):007:0> h[3] = h[3] || 'not false'
=> "not false"

[0] http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-t...

- --
Phillip Gawlowski
Twitter: twitter.com/cynicalryan
Blog: http://justarubyist.bl...

~ 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....

iEYEARECAAYFAkgaJxMACgkQbtAgaoJTgL8e0QCdHbW1PniEGPZSlC9Api4lIL7u
viAAnis9nThp0JAXQEwGWU+JEM5s+ssL
=3HqG
-----END PGP SIGNATURE-----

Phillip Gawlowski

5/1/2008 8:38:00 PM

0

-----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
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.

- --
Phillip Gawlowski
Twitter: twitter.com/cynicalryan
Blog: http://justarubyist.bl...

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....

iEYEARECAAYFAkgaKhoACgkQbtAgaoJTgL/LkgCeMqByMe50+mJx/j8vV3KC612p
lF4AnAz+GVlTLKNPdcjZnsFbbTTwHebv
=Tkje
-----END PGP SIGNATURE-----

David A. Black

5/1/2008 8:42:00 PM

0

HI --

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 <dblack@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.
>
> See:
>
> irb(main):001:0> h = Hash.new
> => {}
> irb(main):002:0> h[1].nil?
> => true
> irb(main):003:0> h[1] = h[1] || 10
> => 10
> irb(main):004:0> h[2] = 'not nil'
> => "not nil"
> irb(main):005:0> h[2] = h[2] || 'a value'
> => "not nil"
> irb(main):006:0> h[3] = false
> => false
> irb(main):007:0> h[3] = h[3] || 'not false'
> => "not false"

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.r... for details and updates!