[lnkForumImage]
TotalShareware - Download Free Software

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


 

James Byrne

5/5/2009 7:51:00 PM

Can someone point out to me where exactly in the API I find a discussion
of the '=||' operator? Or am I imagining things and this does not
really exist?
--
Posted via http://www.ruby-....

16 Answers

Eleanor McHugh

5/5/2009 7:54:00 PM

0

On 5 May 2009, at 20:51, James Byrne wrote:
> Can someone point out to me where exactly in the API I find a
> discussion
> of the '=||' operator? Or am I imagining things and this does not
> really exist?


Are you referring to ||= ? If so it's one of the augmented assignment
operators so you won't find it documented separately as it's syntactic
sugar for:

x = x || some_other_value


Ellie

Eleanor McHugh
Games With Brains
http://slides.games-with-...
----
raise ArgumentError unless @reality.responds_to? :reason



James Byrne

5/5/2009 7:55:00 PM

0

James Byrne wrote:
> Or am I imagining things and this does not really exist?

Maybe I should look for '||=' instead. Sorry.

--
Posted via http://www.ruby-....

Joe Gutierrez

5/5/2009 7:55:00 PM

0

Here's a link for Ruby's operator expressions

http://phrogz.net/ProgrammingRuby/lan...

Joseph Gutierrez
Web Developer - Inc21
jgutierrez@inc21.com



Eleanor McHugh wrote:
> On 5 May 2009, at 20:51, James Byrne wrote:
>> Can someone point out to me where exactly in the API I find a discussion
>> of the '=||' operator? Or am I imagining things and this does not
>> really exist?
>
>
> Are you referring to ||= ? If so it's one of the augmented assignment
> operators so you won't find it documented separately as it's syntactic
> sugar for:
>
> x = x || some_other_value
>
>
> Ellie
>
> Eleanor McHugh
> Games With Brains
> http://slides.games-with-...
> ----
> raise ArgumentError unless @reality.responds_to? :reason
>
>
>
>

--
This message has been scanned for viruses and
dangerous content by MailScanner, and is
believed to be clean.


7stud --

5/5/2009 11:10:00 PM

0

Eleanor McHugh wrote:
> Are you referring to ||= ? If so it's one of the augmented assignment
> operators so you won't find it documented separately as it's syntactic
> sugar for:
>
> x = x || some_other_value
>
>

Nope.

h = Hash.new(10)

h["red"] = h["red"] || 20

--output:--
{"red"=>10}


h = Hash.new(10)
h["blue"] ||= 20
p h

--output:--
{}


The statement:

x ||= val

is actually equivalent to:

x = val unless x

--
Posted via http://www.ruby-....

Eleanor McHugh

5/6/2009 12:45:00 AM

0

On 6 May 2009, at 00:09, 7stud -- wrote:
> Eleanor McHugh wrote:
>> Are you referring to ||= ? If so it's one of the augmented assignment
>> operators so you won't find it documented separately as it's
>> syntactic
>> sugar for:
>>
>> x = x || some_other_value
>
> Nope.
>
> h = Hash.new(10)
>
> h["red"] = h["red"] || 20
>
> --output:--
> {"red"=>10}
>
>
> h = Hash.new(10)
> h["blue"] ||= 20
> p h
>
> --output:--
> {}
>
>
> The statement:
>
> x ||= val
>
> is actually equivalent to:
>
> x = val unless x


It seems you've misunderstood what happens under the hood when using
augmented assignment with tables as '||=' then becomes syntactic sugar
for 'x[] = x[] || some_other_value' and the assignment is performed
via '[]=' rather than '='. '[]=' will not create a key if it believes
it already exists and this is the cause of the behaviour you're seeing.

h = Hash.new(10)
p h["blue"] => 10
h["blue"] ||= 20
p h => {}

In this case when '||=' invokes the assignment it finds that h["blue"]
already contains a value because of the default so the hash method
'[]=' doesn't attempt to create a new key because it appears that the
key already exists.

Contrast this to:

h = Hash.new(10)
p h["blue"] => 10
h["blue"] = nil
p h => { "blue" => nil }
h["blue"] ||= 10
p h => { "blue" => 10 }
h["blue"] ||= 20
p h => { "blue" => 10 }

Here the key has been explicitly set equal to nil and '||=' acts the
way we'd expect an augmented assignment to work with scalar types.

Finally if no default is set for the table:

h = {}
h["red"] ||= 10
p h => {"red" => 10}

The key is always created as expected.


Ellie

Eleanor McHugh
Games With Brains
http://slides.games-with-...
----
raise ArgumentError unless @reality.responds_to? :reason



Rick DeNatale

5/6/2009 1:32:00 AM

0

On Tue, May 5, 2009 at 8:45 PM, Eleanor McHugh
<eleanor@games-with-brains.com> wrote:
> On 6 May 2009, at 00:09, 7stud -- wrote:
>>
>> Eleanor McHugh wrote:
>>>
>>> Are you referring to ||= ? If so it's one of the augmented assignment
>>> operators so you won't find it documented separately as it's syntactic
>>> sugar for:
>>>
>>> x = x || some_other_value
>>
>> Nope.
...
>> The statement:
>>
>> x ||= val
>>
>> is actually equivalent to:
>>
>> x = val unless x
>
>
> It seems you've misunderstood what happens under the hood when using
> augmented assignment with tables as '||=' then becomes syntactic sugar for
> 'x[] = x[] || some_other_value' and the assignment is performed via '[]='
> rather than '='. '[]=' will not create a key if it believes it already
> exists and this is the cause of the behaviour you're seeing.

No, if x is truthy then

x ||= expression

will NOT do any assignment.

The real equivalent to x ||= y

is

x || x = y

The assignment is short-circuited.

For the proof see:

http://talklikeaduck.denh...2008/04/26...


--
Rick DeNatale

Blog: http://talklikeaduck.denh...
Twitter: http://twitter.com/Ri...
WWR: http://www.workingwithrails.com/person/9021-ric...
LinkedIn: http://www.linkedin.com/in/ri...

7stud --

5/6/2009 1:38:00 AM

0

Eleanor McHugh wrote:
> On 6 May 2009, at 00:09, 7stud -- wrote:
>> h = Hash.new(10)
>>
>> x = val unless x
> It seems you've misunderstood what happens under the hood when using
> augmented assignment with tables as '||=' then becomes syntactic sugar
> for 'x[] = x[] || some_other_value' and the assignment is performed
> via '[]=' rather than '='. '[]=' will not create a key if it believes
> it already exists and this is the cause of the behaviour you're seeing.
>
> h = Hash.new(10)
> p h["blue"] => 10
> h["blue"] ||= 20
> p h => {}
>
> In this case when '||=' invokes the assignment it finds that h["blue"]
> already contains a value because of the default so the hash method
> '[]=' doesn't attempt to create a new key because it appears that the
> key already exists.
>
> Contrast this to:
>
> h = Hash.new(10)
> p h["blue"] => 10
> h["blue"] = nil
> p h => { "blue" => nil }
> h["blue"] ||= 10
> p h => { "blue" => 10 }
> h["blue"] ||= 20
> p h => { "blue" => 10 }
>
> Here the key has been explicitly set equal to nil and '||=' acts the
> way we'd expect an augmented assignment to work with scalar types.
>
> Finally if no default is set for the table:
>
> h = {}
> h["red"] ||= 10
> p h => {"red" => 10}
>
> The key is always created as expected.
>


Why do I need to care about what's going on under the hood? If two
things
produce different results, then how can one be considered syntactic
sugar for the other. In my opinion, "syntactic sugar" means that the
two formats can
be used interchangeably--with experienced programmers naturally
gravitating to the shorter, easier to type format, and inexperienced
programmers preferring the longer, but easier to understand format.

--
Posted via http://www.ruby-....

Eleanor McHugh

5/6/2009 10:45:00 AM

0

On 6 May 2009, at 02:38, 7stud -- wrote:
> Why do I need to care about what's going on under the hood?

Because when things don't work the way you expect, looking under the
hood allows you to adjust your expectations ;)

> If two
> things
> produce different results, then how can one be considered syntactic
> sugar for the other. In my opinion, "syntactic sugar" means that the
> two formats can
> be used interchangeably--with experienced programmers naturally
> gravitating to the shorter, easier to type format, and inexperienced
> programmers preferring the longer, but easier to understand format.

All that syntactic sugar means is that one phrase is equivalent to
another syntactically, not that they're semantically equivalent.
However in the case of 'x = x || y' and 'x[n] = x[n] || y' are they
even syntactically equivalent? No. They appear syntactically similar,
but one invokes the '=' assignment operator whereas the other sends
the '[]=' message to the receiver. And because '[]=' leaves the
semantics of assignment to the receiver, that allows for the
differences you're seeing in this case.


Ellie

Eleanor McHugh
Games With Brains
http://slides.games-with-...
----
raise ArgumentError unless @reality.responds_to? :reason



Eleanor McHugh

5/6/2009 10:54:00 AM

0

On 6 May 2009, at 02:31, Rick DeNatale wrote:
> On Tue, May 5, 2009 at 8:45 PM, Eleanor McHugh
> <eleanor@games-with-brains.com> wrote:
>> On 6 May 2009, at 00:09, 7stud -- wrote:
>>> The statement:
>>>
>>> x ||= val
>>>
>>> is actually equivalent to:
>>>
>>> x = val unless x
>>
>>
>> It seems you've misunderstood what happens under the hood when using
>> augmented assignment with tables as '||=' then becomes syntactic
>> sugar for
>> 'x[] = x[] || some_other_value' and the assignment is performed via
>> '[]='
>> rather than '='. '[]=' will not create a key if it believes it
>> already
>> exists and this is the cause of the behaviour you're seeing.
>
> No, if x is truthy then
>
> x ||= expression
>
> will NOT do any assignment.
>
> The real equivalent to x ||= y
>
> is
>
> x || x = y
>
> The assignment is short-circuited.
>
> For the proof see:
>
> http://talklikeaduck.denhaven2.com/2008/04/26...

Yes, for assignment that's the case. But 'x[n] ||= y' isn't an
instance of assignment in that case as can easily be demonstrated:

class Test
def method_missing symbol, *args
puts "calling method #{symbol}"
end
end

t = Test.new
t[:a] ||= 17

output: calling method []
calling method []=

Notice how even though method_missing returns a value and is thus
'true' the sequence still attempts all parts of the expression, and

t[:a] = t[:a] || 17

output: calling method []
calling method []=
=> 17

confirms that no short-circuited evaluation occurs.


Ellie

Eleanor McHugh
Games With Brains
http://slides.games-with-...
----
raise ArgumentError unless @reality.responds_to? :reason



Rick DeNatale

5/6/2009 12:04:00 PM

0

On Wed, May 6, 2009 at 6:54 AM, Eleanor McHugh
<eleanor@games-with-brains.com> wrote:
> On 6 May 2009, at 02:31, Rick DeNatale wrote:
>>
>> On Tue, May 5, 2009 at 8:45 PM, Eleanor McHugh
>> <eleanor@games-with-brains.com> wrote:
>>>
>>> On 6 May 2009, at 00:09, 7stud -- wrote:
>>>>
>>>> The statement:
>>>>
>>>> x ||=3D val
>>>>
>>>> is actually equivalent to:
>>>>
>>>> x =3D val unless x
>>>
>>>
>>> It seems you've misunderstood what happens under the hood when using
>>> augmented assignment with tables as '||=3D' then becomes syntactic suga=
r
>>> for
>>> 'x[] =3D x[] || some_other_value' and the assignment is performed via '=
[]=3D'
>>> rather than '=3D'. '[]=3D' will not create a key if it believes it alre=
ady
>>> exists and this is the cause of the behaviour you're seeing.
>>
>> No, if x is truthy then
>>
>> =A0x ||=3D expression
>>
>> will NOT do any assignment.
>>
>> The real equivalent to x ||=3D y
>>
>> is
>>
>> x || x =3D y
>>
>> The assignment is short-circuited.
>>
>> For the proof see:
>>
>> http://talklikeaduck.denh...2008/04/26...
>
> Yes, for assignment that's the case. But 'x[n] ||=3D y' isn't an instance=
of
> assignment in that case as can easily be demonstrated:
>
> class Test
> =A0def method_missing symbol, *args
> =A0 =A0puts "calling method #{symbol}"
> =A0end
> end
>
> t =3D Test.new
> t[:a] ||=3D 17
>
> output: calling method []
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0calling method []=3D
>
> Notice how even though method_missing returns a value and is thus 'true' =
the
> sequence still attempts all parts of the expression, and
>
> t[:a] =3D t[:a] || 17
>
> output: calling method []
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0calling method []=3D
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=3D> 17
>
> confirms that no short-circuited evaluation occurs.
>

But this is because the call to the missing [] method goes to the
method missing method which returns nil.

Remember that the assertion is that

t[:a] ||=3D 17

is equivalent to

(t[:a]) || (t[:a] =3D 17)

which in turn is equivalent to:

((t.[](:a)) || (t.[]=3D(:a, 17))

The output of your example shows both the :[] and :[]=3D methods are being =
sent.

Try this variant:

class Test
def method_missing symbol, *args
puts "calling method #{symbol}"
end

def [](a)
puts "in [] method"
a
end
end

t =3D Test.new
t[:a] ||=3D 17

This produces the output;
in [] method

The short circuiting only happens if the lhs expression returns a
non-truthy value.

Now it's true (I think) that "a op=3D b" is the same as "a =3D a op b" in
C, Ruby ain't C.

Sometimes the stuff "under the hood" is a little more complicated than
it first appears. <G>

--=20
Rick DeNatale

Blog: http://talklikeaduck.denh...
Twitter: http://twitter.com/Ri...
WWR: http://www.workingwithrails.com/person/9021-ric...
LinkedIn: http://www.linkedin.com/in/ri...