[lnkForumImage]
TotalShareware - Download Free Software

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


 

Forums >

comp.lang.ruby

The ||= assignment operator

Belorion

4/4/2008 7:12:00 PM

[Note: parts of this message were removed to make it a legal post.]

It was my understanding that the ||= assignment operator assigned the value
on the right-hand side if and only if the left hand side did not already
have a value:

irb(main):001:0> x = true
=> true
irb(main):002:0> x ||= "ruby"
=> true
irb(main):003:0> x
=> true
And, likewise, with nil:

irb(main):014:0> x = nil
=> nil
irb(main):015:0> x ||= "ruby"
=> "ruby"
irb(main):016:0> x
=> "ruby"
However, I do not understand this behavior:

irb(main):019:0> x = false
=> false
irb(main):020:0> x ||= "ruby"
=> "ruby"
irb(main):021:0> x
=> "ruby"


We know that false != nil, and yet the ||= will assign if the left hand side
is false?

regards,
Matt

30 Answers

Glen Holcomb

4/4/2008 7:25:00 PM

0

[Note: parts of this message were removed to make it a legal post.]

On Fri, Apr 4, 2008 at 1:11 PM, Belorion <belorion@gmail.com> wrote:

> It was my understanding that the ||= assignment operator assigned the
> value
> on the right-hand side if and only if the left hand side did not already
> have a value:
>
> irb(main):001:0> x = true
> => true
> irb(main):002:0> x ||= "ruby"
> => true
> irb(main):003:0> x
> => true
> And, likewise, with nil:
>
> irb(main):014:0> x = nil
> => nil
> irb(main):015:0> x ||= "ruby"
> => "ruby"
> irb(main):016:0> x
> => "ruby"
> However, I do not understand this behavior:
>
> irb(main):019:0> x = false
> => false
> irb(main):020:0> x ||= "ruby"
> => "ruby"
> irb(main):021:0> x
> => "ruby"
>
>
> We know that false != nil, and yet the ||= will assign if the left hand
> side
> is false?
>
> regards,
> Matt
>

Nope ||= will assign if nil or false.

--
"Hey brother Christian with your high and mighty errand, Your actions speak
so loud, I can't hear a word you're saying."

-Greg Graffin (Bad Religion)

Todd Benson

4/4/2008 7:28:00 PM

0

On Fri, Apr 4, 2008 at 2:11 PM, Belorion <belorion@gmail.com> wrote:
> It was my understanding that the ||= assignment operator assigned the value
> on the right-hand side if and only if the left hand side did not already
> have a value:
>
> irb(main):001:0> x = true
> => true
> irb(main):002:0> x ||= "ruby"
> => true
> irb(main):003:0> x
> => true
> And, likewise, with nil:
>
> irb(main):014:0> x = nil
> => nil
> irb(main):015:0> x ||= "ruby"
> => "ruby"
> irb(main):016:0> x
> => "ruby"
> However, I do not understand this behavior:
>
> irb(main):019:0> x = false
> => false
> irb(main):020:0> x ||= "ruby"
> => "ruby"
> irb(main):021:0> x
> => "ruby"
>
>
> We know that false != nil, and yet the ||= will assign if the left hand side
> is false?
>
> regards,
> Matt

The operators are working with a three-valued logic. In a comparison,
a FalseClass object or a NilClass object will be logistically false.

Todd

Paul Mucur

4/4/2008 7:30:00 PM

0

On 4 Apr 2008, at 20:11, Belorion wrote:

> It was my understanding that the ||= assignment operator assigned
> the value
> on the right-hand side if and only if the left hand side did not
> already
> have a value:

It's probably better to think of x ||= "ruby" as being short hand for
x = x || "ruby" (which it effectively is) instead of "assign if not
already having a value". If you do this, then you can see why your
last example behaves like it does.

Don't forget that there are other similar operators like +=, -= and
&&= and they all follow the same pattern:

x ?= y
x = x ? y

Where ? is one of -, +, && or ||.

Hope that this helps.

Belorion

4/4/2008 7:42:00 PM

0

[Note: parts of this message were removed to make it a legal post.]

Thanks all, that clears up my understanding. I hadn't thought of it as x =
x || "ruby" (even thoughI knew that x += 1 is the same as x = x + 1) and
that in that expanded case, x evaluates, logistically, to false if nil or
false.

Matt

On Fri, Apr 4, 2008 at 2:28 PM, Todd Benson <caduceass@gmail.com> wrote:

> On Fri, Apr 4, 2008 at 2:11 PM, Belorion <belorion@gmail.com> wrote:
> > It was my understanding that the ||= assignment operator assigned the
> value
> > on the right-hand side if and only if the left hand side did not
> already
> > have a value:
> >
> > irb(main):001:0> x = true
> > => true
> > irb(main):002:0> x ||= "ruby"
> > => true
> > irb(main):003:0> x
> > => true
> > And, likewise, with nil:
> >
> > irb(main):014:0> x = nil
> > => nil
> > irb(main):015:0> x ||= "ruby"
> > => "ruby"
> > irb(main):016:0> x
> > => "ruby"
> > However, I do not understand this behavior:
> >
> > irb(main):019:0> x = false
> > => false
> > irb(main):020:0> x ||= "ruby"
> > => "ruby"
> > irb(main):021:0> x
> > => "ruby"
> >
> >
> > We know that false != nil, and yet the ||= will assign if the left hand
> side
> > is false?
> >
> > regards,
> > Matt
>
> The operators are working with a three-valued logic. In a comparison,
> a FalseClass object or a NilClass object will be logistically false.
>
> Todd
>
>

Todd Benson

4/4/2008 7:52:00 PM

0

On Fri, Apr 4, 2008 at 2:41 PM, Belorion <belorion@gmail.com> wrote:
> Thanks all, that clears up my understanding. I hadn't thought of it as x =
> x || "ruby" (even thoughI knew that x += 1 is the same as x = x + 1) and
> that in that expanded case, x evaluates, logistically, to false if nil or
> false.

For conditional expressions. Here's something that may catch you off guard...

irb(main):001:0> nil || false
=> false
irb(main):001:0> false || nil
=> nil

Todd

Chris Shea

4/4/2008 8:15:00 PM

0

On Apr 4, 1:30 pm, Paul Mucur <mu...@waferbaby.com> wrote:
> On 4 Apr 2008, at 20:11, Belorion wrote:
>
> > It was my understanding that the ||= assignment operator assigned
> > the value
> > on the right-hand side if and only if the left hand side did not
> > already
> > have a value:
>
> It's probably better to think of x ||= "ruby" as being short hand for
> x = x || "ruby" (which it effectively is) instead of "assign if not
> already having a value". If you do this, then you can see why your
> last example behaves like it does.
>
> Don't forget that there are other similar operators like +=, -= and
> &&= and they all follow the same pattern:
>
> x ?= y
> x = x ? y
>
> Where ? is one of -, +, && or ||.
>
> Hope that this helps.

It's better to think of x ||= "ruby" as x || x = "ruby".

--
h = Hash.new('default value')

h[:test] ||= 'assigned value'
h # => {}

# same as:
h[:test] || h[:test] = 'assigned value'
h # => {}

# not:
h[:test] = h[:test] || 'assigned value'
h # => {:test=>"default value"}
--

Chris

Peña, Botp

4/5/2008 3:29:00 AM

0

From: Chris Shea [mailto:cmshea@gmail.com]=20
# It's better to think of x ||=3D "ruby" as x || x =3D "ruby".
#=20
# --
# h =3D Hash.new('default value')
#=20
# h[:test] ||=3D 'assigned value'
# h # =3D> {}
#=20
# # same as:
# h[:test] || h[:test] =3D 'assigned value'
# h # =3D> {}
#=20
# # not:
# h[:test] =3D h[:test] || 'assigned value'
# h # =3D> {:test=3D>"default value"}


i'd say that's a bug in design (unless x+=3D1 is now x+x=3D1 ;)

kind regards -botp


Avdi Grimm

4/5/2008 3:53:00 AM

0

On this topic, am I the only one who would really like to see a
dedicated "defaulting operator" in Ruby? Something that actually has
the semantics which a lot of people mistakenly assume for ||=, i.e.
"assign if and only if nil"? I think Perl6 uses the //= operator for
this. This is such a subtle gotcha. I've seen a lot of code that was
potentially buggy because it didn't account for the fact that the
'false' value would be handled incorrectly.

--
Avdi

Steve Ross

4/5/2008 4:39:00 AM

0

On Apr 4, 2008, at 8:53 PM, Avdi Grimm wrote:

> On this topic, am I the only one who would really like to see a
> dedicated "defaulting operator" in Ruby? Something that actually has
> the semantics which a lot of people mistakenly assume for ||=, i.e.
> "assign if and only if nil"? I think Perl6 uses the //= operator for
> this. This is such a subtle gotcha. I've seen a lot of code that was
> potentially buggy because it didn't account for the fact that the
> 'false' value would be handled incorrectly.
>
> --
> Avdi

This would be great, but you would need both a // and //= operator.
Consider this:

@my_web_page_title = @page_name || "d'oh! you forgot to name your page"

You would want to rewrite this as:

@my_web_page_title = @page_name // "d'oh! you forgot to name your page"

It would seem that adding these operators has a low potential to
introduce bugs into working code and, as you point out, there are
subtleties WRT the ||= idiom. Moving it from idiom to first-class
operator might clarify those subtleties.


Joshua Ballanco

4/5/2008 5:46:00 AM

0

Peña, Botp wrote:
> From: Chris Shea [mailto:cmshea@gmail.com]
> # It's better to think of x ||= "ruby" as x || x = "ruby".
> #
> # --
> # h = Hash.new('default value')
> #
> # h[:test] ||= 'assigned value'
> # h # => {}
> #
> # # same as:
> # h[:test] || h[:test] = 'assigned value'
> # h # => {}
> #
> # # not:
> # h[:test] = h[:test] || 'assigned value'
> # h # => {:test=>"default value"}
>
>
> i'd say that's a bug in design (unless x+=1 is now x+x=1 ;)
>
> kind regards -botp

Not at all. Rather, this is just a subtle misunderstanding of how hash
is implemented. Consider the following:

>> h = Hash.new
=> {}
>> h[:test] ||= 'testing without default'
=> "testing without default"
>> h
=> {:test=>"testing without default"}
>> h = Hash.new('default value')
=> {}
>> h[:test] ||= 'testing with default'
=> "default value"
>> h
=> {}

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).
Consider further:

>> h = Hash.new
=> {}
>> puts 'empty' unless h[:test]
empty
=> nil
>> h = Hash.new('default value')
=> {}
>> puts 'empty' unless h[:test]
=> nil
>>

I think the confusion is that, in Chris' example, there's no assignment,
so the hash only holds the default value temporarily (i.e. just long
enough to not evaluate to nil or false).
--
Posted via http://www.ruby-....