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-forum.com/.
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-forum.com/.
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-brains.net
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?
----
raise ArgumentError unless @reality.responds_to? :reason
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-forum.com/\.
Here's a link for Ruby's operator expressions
http://phrogz.net/ProgrammingRuby/language.html
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-brains.net
----
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.
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-forum.com/\.
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-brains.net
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
----
raise ArgumentError unless @reality.responds_to? :reason
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.denhaven2.com/2008/04/26/x-y-redux
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:
--
Rick DeNatale
Blog: http://talklikeaduck.denhaven2.com/
Twitter: http://twitter.com/RickDeNatale
WWR: http://www.workingwithrails.com/person/9021-rick-denatale
LinkedIn: http://www.linkedin.com/in/rickdenatale
Eleanor McHugh 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.
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-brains.net
On 6 May 2009, at 02:38, 7stud -- wrote:
----
raise ArgumentError unless @reality.responds_to? :reason
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-brains.net
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:
----
raise ArgumentError unless @reality.responds_to? :reason
Eleanor McHugh:
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'
No, puts returns nil.
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.
class Test
def method_missing symbol, *args
puts "calling method #{symbol}"
true
end
end
t = Test.new
t[:a] ||= 17
# calling method
t[:a] = t[:a] || 17
# calling method
# calling method =
— Shot
--
Google Trends says CiviCRM is as popular as blueberry
pancakes. Woo!! Next up: waffles! [Wes Morgan]
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] ||= 17
is equivalent to
(t[:a]) || (t[:a] = 17)
which in turn is equivalent to:
((t.(:a)) || (t.=(:a, 17))
The output of your example shows both the : and := 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 = Test.new
t[:a] ||= 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= b" is the same as "a = 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>
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 ||= 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:
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
endt = Test.new
t[:a] ||= 17output: 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, andt[:a] = t[:a] || 17
output: calling method
calling method =
=> 17confirms that no short-circuited evaluation occurs.
--
Rick DeNatale
Blog: http://talklikeaduck.denhaven2.com/
Twitter: http://twitter.com/RickDeNatale
WWR: http://www.workingwithrails.com/person/9021-rick-denatale
LinkedIn: http://www.linkedin.com/in/rickdenatale
I should have mentioned in my reply that since your method missing
body consists of a single puts statement, and since puts returns nil,
that value is non-truthy
and
nil || x
is x which is why the = gets sent in your example.
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:
Notice how even though method_missing returns a value and is thus 'true' the
sequence still attempts all parts of the expression, and
--
Rick DeNatale
Blog: http://talklikeaduck.denhaven2.com/
Twitter: http://twitter.com/RickDeNatale
WWR: http://www.workingwithrails.com/person/9021-rick-denatale
LinkedIn: http://www.linkedin.com/in/rickdenatale
The short circuiting only happens if the lhs expression returns a
non-truthy value.Now it's true (I think) that "a op= b" is the same as "a = 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>
Very true, and we all learn new stuff by considering it. For example I suspect quite a few people would be surprised by the following code:
class Test
def initialize
@switch = false
end
def x
puts "[#{x}]"
@switch = !@switch
end
def = x, y
puts "[#{x}] = #{y}"
end
end
t = Test.new
t[:a] ||= 17
output: [a]
[a]
here the '' call returns 'true' and 'false' by turns but in either event the assignment fails to call '='...
Ellie
Eleanor McHugh
Games With Brains
http://slides.games-with-brains.net
On 6 May 2009, at 13:03, Rick DeNatale wrote:
----
raise ArgumentError unless @reality.responds_to? :reason
doh! I knew that
Ellie
Eleanor McHugh
Games With Brains
http://slides.games-with-brains.net
On 6 May 2009, at 12:50, Shot (Piotr Szotkowski) wrote:
Eleanor McHugh:
No, puts returns nil.
----
raise ArgumentError unless @reality.responds_to? :reason
Perhaps I should have paid more attention to my morning email spam regarding 'retrograde mercury'...
Ellie
Eleanor McHugh
Games With Brains
http://slides.games-with-brains.net
On 6 May 2009, at 13:05, Rick DeNatale wrote:
I should have mentioned in my reply that since your method missing
body consists of a single puts statement, and since puts returns nil,
that value is non-truthyand
nil || x
is x which is why the = gets sent in your example.
----
raise ArgumentError unless @reality.responds_to? :reason
Are you sure? When I run your code I get this:
[a]
[a]
[a] = 17
[a]
On Wed, May 6, 2009 at 9:43 AM, Eleanor McHugh <eleanor@games-with-brains.com> wrote:
On 6 May 2009, at 13:03, Rick DeNatale wrote:
The short circuiting only happens if the lhs expression returns a
non-truthy value.Now it's true (I think) that "a op= b" is the same as "a = 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>Very true, and we all learn new stuff by considering it. For example I
suspect quite a few people would be surprised by the following code:class Test
def initialize
@switch = false
enddef x
puts "[#{x}]"
@switch = !@switch
enddef = x, y
puts "[#{x}] = #{y}"
end
endt = Test.new
t[:a] ||= 17
t[:a] ||= 17
t[:a] ||= 17output: [a]
[a]
[a]here the '' call returns 'true' and 'false' by turns but in either event
the assignment fails to call '='...
--
Rick DeNatale
Blog: http://talklikeaduck.denhaven2.com/
Twitter: http://twitter.com/RickDeNatale
WWR: http://www.workingwithrails.com/person/9021-rick-denatale
LinkedIn: http://www.linkedin.com/in/rickdenatale
I typed '||' for '||=' when I ran that in irb, hence the 'mercury retrograde' comment elsewhere...
Anyway it seems I'm suffering from an IAK meltdown today so it's probably best if I step away from the keyboard before any more innocent bytes get hurt
Ellie
Eleanor McHugh
Games With Brains
http://slides.games-with-brains.net
On 6 May 2009, at 14:59, Rick DeNatale wrote:
Are you sure? When I run your code I get this:
[a]
[a] = 17
[a]
----
raise ArgumentError unless @reality.responds_to? :reason