Shorthand

I read this once:

Operator ||= can be shorthand for code like:
x = “(some fallback value)” unless respond_to? :x or x

How would that look like exactly, in shorthand, any guesses?
-r

Roger P. wrote:

I read this once:

Operator ||= can be shorthand for code like:
x = “(some fallback value)” unless respond_to? :x or x

How would that look like exactly, in shorthand, any guesses?

foo ||= 5

is shorthand for

foo = foo || 5

which means
(a) ‘foo’ is a local variable (because it’s an assignment)
(b) it will be set to 5 if it is currently nil or false, otherwise it
will retain its previous value.

The thing you read about respond_to? is wrong. This construct is nothing
to do with a method called foo, as you can easily demonstrate:

$ irb --simple-prompt

def foo
9
end
=> nil

respond_to? :foo
=> true

foo ||= 5
=> 5

foo
=> 5

On 2010-06-14 14:48:36 -0700, Roger P. said:

I read this once:

Operator ||= can be shorthand for code like:
x = “(some fallback value)” unless respond_to? :x or x

How would that look like exactly, in shorthand, any guesses?
-r

The expression:

a ||= b

is equivalent to:

a || a = b

in most cases. To be pedantic, it is actually:

(defined?(a) && a) || a = b

and does not raise an error for undefined local variables. This is also
true of `&&=’.

Note:

The code:

x = “some value”

will always set the local variable x', whether there is a methodx’
on self or not, so your code that uses respond_to? will not behave as
you expect it to.

Another note:

the expression (in pseudocode):

a = b

is equivalent to:

a = a b

except where is || or &&, where the above applies.

Examples:

a = 1
a += 5
a *= 10

a # => 60

b = [:foo, :bar]
b |= [:bar, :bizz]

b # => [:foo, :bar, :bizz]

flag = 0b01
flag |= 0b10
flag.to_s(2) # => “11”

Roger P. [email protected] writes:

I read this once:

Operator ||= can be shorthand for code like:
x = “(some fallback value)” unless respond_to? :x or x

How would that look like exactly, in shorthand, any guesses?
-r

Sure you don’t mean ||= as a way of easily implementing basic
memoization?

Example:

class Foo
def bar
@bar ||= begin
# do some calculations here
1 + rand
end
end
end

f = Foo.new
f.bar # => 1.01853966346202
f.bar # => 1.01853966346202

On Mon, Jun 14, 2010 at 5:48 PM, Roger P. rem[email protected]
wrote:

I read this once:

Operator ||= can be shorthand for code like:
x = “(some fallback value)” unless respond_to? :x or x

How would that look like exactly, in shorthand, any guesses?

I don’t know where you read that, but it has no basis in reality. The
semantics of ||= have nothing to do with whether or not a method
exists.

The closest translation of

x ||= y

(x || x = y)

This is close, except that it will blow up if x isn’t already defined.

another alternative might be

(defined? x) ? (x || x = y) : y

Which avoids the problem when x isn’t defined, but isn’t exactly what
the ‘compiled’ ruby code does, whether that ‘code’ is YARV ‘byte
codes’ or an AST in MRI pre 1.9


Rick DeNatale

Blog: http://talklikeaduck.denhaven2.com/
Github: http://github.com/rubyredrick
Twitter: @RickDeNatale
WWR: http://www.workingwithrails.com/person/9021-rick-denatale
LinkedIn: http://www.linkedin.com/in/rickdenatale

On Mon, Jun 14, 2010 at 8:35 PM, Josh C. [email protected]
wrote:

codes’ or an AST in MRI pre 1.9

This implies to me that if x is not defined, then return y without modifying
x. But this contradicts the reason I used ||= for (lazy assignment).

Yeah it was a typo on my part

(defined? x) ? (x || x = y) : (x = y)

As I said before though, all of these are approximations. The
defined? guard is just to avoid the undefined variable error.

For

x ||= y

The compiler defines x when it sees it, normally a local variable only
gets defined when it actually gets a value assigned.


Rick DeNatale

Blog: http://talklikeaduck.denhaven2.com/
Github: http://github.com/rubyredrick
Twitter: @RickDeNatale
WWR: http://www.workingwithrails.com/person/9021-rick-denatale
LinkedIn: http://www.linkedin.com/in/rickdenatale

On Tue, Jun 15, 2010 at 1:24 PM, Brian C. [email protected]
wrote:

foo ||= 5

is shorthand for

foo = foo || 5

NO it is NOT, although many Rubyist seem to cling to this idea.

see http://talklikeaduck.denhaven2.com/2008/04/26/x-y-redux

and recent discussion on this very thread.

The difference between

x ||= 5

and

x = x | | 5

is that if x has a truthy value, then NO assignment will be done in
the first case (including assignment through a ‘setter’ method) in the
first case, but it will in the second.


Rick DeNatale

Blog: http://talklikeaduck.denhaven2.com/
Github: http://github.com/rubyredrick
Twitter: @RickDeNatale
WWR: http://www.workingwithrails.com/person/9021-rick-denatale
LinkedIn: http://www.linkedin.com/in/rickdenatale

On 6/14/10, Rein H. [email protected] wrote:

The expression:

a ||= b

is equivalent to:

a || a = b

in most cases. To be pedantic, it is actually:

(defined?(a) && a) || a = b

Except if there’s a method named a, defined?(a) returns “method”, so
this still isn’t exactly equivalent. Ruby is tricksy.

On 2010-06-14 15:41:09 -0700, Rick DeNatale said:

semantics of ||= have nothing to do with whether or not a method
another alternative might be
Blog: http://talklikeaduck.denhaven2.com/
Github: http://github.com/rubyredrick
Twitter: @RickDeNatale
WWR: http://www.workingwithrails.com/person/9021-rick-denatale
LinkedIn: http://www.linkedin.com/in/rickdenatale

Rick,

Can we combine the contents of the thousands of messages explaining the
behavior of = into a blog post and just start referencing it?
Oh wait, didn’t you do that? :wink:

We need a FAQ :smiley:

On 2010-06-14 17:21:00 -0700, Caleb C. said:

(defined?(a) && a) || a = b

Except if there’s a method named a, defined?(a) returns “method”, so
this still isn’t exactly equivalent. Ruby is tricksy.

Yes, thank you for your meta-pedantry :wink:

It is not actually implemented as such but the behavior is very similar.

Rick Denatale wrote:

The difference between

x ||= 5

and

x = x | | 5

is that if x has a truthy value, then NO assignment will be done in
the first case (including assignment through a ‘setter’ method) in the
first case, but it will in the second.

I never said that foo.x ||= 5 behaves like this. This is a method call
(:x=) not a local variable assignment.

class Foo
def initialize(x=nil)
self.x = x
end
def x
@x
end
def x=(x)
puts “set to #{x}”
@x = x
end
end
f = Foo.new
f.x ||= 3
f.x ||= 5

On Mon, Jun 14, 2010 at 5:41 PM, Rick DeNatale
[email protected]wrote:

This implies to me that if x is not defined, then return y without
modifying
x. But this contradicts the reason I used ||= for (lazy assignment).

$ irb

ruby-1.9.1-p378 > defined? x
=> nil

ruby-1.9.1-p378 > defined? x
=> nil

ruby-1.9.1-p378 > x ||= 5
=> 5

ruby-1.9.1-p378 > x
=> 5

On Thu, Jun 17, 2010 at 11:07 AM, Brian C. [email protected]
wrote:

I never said that foo.x ||= 5 behaves like this. This is a method call
(:x=) not a local variable assignment.

No, but you said that “foo ||= 5 is shorthand for foo = foo || 5”
which implies the same semantics, but…

class Foo
def initialize(x=nil)
self.x = x
end
def x
@x
end
def x=(x)
puts “set to #{x}”
@x = x
end
end
f = Foo.new
f.x ||= 3
f.x ||= 5

f.x = f.x || 6

produces:

set to
set to 3
set to 3

See the difference?


Rick DeNatale

Blog: http://talklikeaduck.denhaven2.com/
Github: http://github.com/rubyredrick
Twitter: @RickDeNatale
WWR: http://www.workingwithrails.com/person/9021-rick-denatale
LinkedIn: http://www.linkedin.com/in/rickdenatale

2010/6/14 Roger P. [email protected]:

I read this once:

Operator ||= can be shorthand for code like:
x = “(some fallback value)” unless respond_to? :x or x

How would that look like exactly, in shorthand, any guesses?

You can do this:

x ||= (x() rescue “(some fallback value)”)

I did not think about this long enough to look at all the effects with
local variables shadowing methods but it’s something you can play
with. :slight_smile:

Kind regards

robert