Pipe question

What does the pipe in this example do?

@first_name = @first_name || ‘’

According to the text book that this example came from, the code ensures
that an instance variable is not nil. If @first_ name is nil, @first_
name is set to the empty string.

Thank you.

An expression like “foo || bar” works like this: First, evaluate the
boolean value of foo. If it is boolean-true, then the value of this
expression is foo. If not, then the value of this expression is
bar.

This expression says, assign the current value of @first_name back
into @first_name. Alternatively, if this is the first time you’re
trying to assign it, it’ll be nil, so use an empty string instead.

It’s equivalent to writing:

@first_name ||= ''

~ jf

John F.
Principal Consultant, BitsBuilder
LI: http://www.linkedin.com/in/johnxf
SO: User John Feminella - Stack Overflow

Ha Ha. I was interpeting the pipes as empty arguments of an empty
block, which made no sence to me. Logical operators didn’t even occure
to me. Seems funny now. Thank you John and Josh for helping me see the
light.

The || is a Logical OR Operator that returns the first true value (in
Ruby anything besides false and nil is true). I ran this demonstration
in irb:

true || true
=> true

true || false
=> true

false || true
=> true

false || false
=> false

1 || 2
=> 1

1 || false
=> 1

false || 2
=> 2

false || false
=> false

1 || 2
=> 1

1 || nil
=> 1

nil || 2
=> 2

nil || nil
=> nil

nil || nil || 3 || 4
=> 3

On Sun, Apr 3, 2011 at 9:58 PM, wolf volpi [email protected] wrote:


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

  1. In Ruby, false and nil are treated as falsy. Everything else is
    treated
    as truthy.

“truthy” if nil # => nil
“truthy” if false # => nil
“truthy” if true # => “truthy”
“truthy” if “str” # => “truthy”
“truthy” if 1 # => “truthy”
“truthy” if 1.23 # => “truthy”
“truthy” if /regex/ # => nil
“truthy” if :symbol # => “truthy”
“truthy” if ‘r’…‘ange’ # => “truthy”

  1. Boolean operators return the objects themselves. In an “or” (double
    pipes), if the first value is falsy, the second value is returned. If
    the
    first value is truthy, it is returned.

nil || “b” # => “b”
false || “b” # => “b”
“a” || nil # => “a”
“a” || false # => “a”
“a” || “b” # => “a”
nil || nil # => nil
nil || false # => false
false || nil # => nil
false || false # => false

  1. For some reason that I don’t know (probably interpreter magic) an
    uninitialized variable can be referenced in a boolean equation and it
    will
    evaluate to nil.

first_name = first_name || “” # => “”
first_name = “josh”
first_name = first_name || “” # => “josh”

So, it will set the variable to the empty string, if the variable is
undeclared, or false , or nil.

On Sun, Apr 3, 2011 at 10:42 PM, Josh C. [email protected]
wrote:

“truthy” if :symbol # => “truthy”
“truthy” if ‘r’…‘ange’ # => “truthy”

I just listed out a bunch of examples and then ran them… But I’m
looking
now, and realize that /regex/ evaluated as falsy! After some playing
around, I have decided that it is based on Perl. If you put a regex in a
variable, it treats it as a boolean “is it an object?” and behaves as I
stated previously. But if you put it in a literal, it plays Perl and
checks
to see if it matches against $_

regex = /re(.)ex/
$_ # => nil

in literal, so checks if it matches $_

(note that it warns: regex literal in condition)

“truthy” if /re(.)ex/ # => nil

in var, so checks if it exists

“truthy” if regex # => “truthy”

explicitly set $_, now literal matches

$_ = “reGex”
“truthy” if /re(.)ex/ # => “truthy”

when we look at capture group, we see the G we made

$1 # => “G”

change the $_ to see if variable matches it

$_ = “reXex”
“truthy” if regex # => “truthy”

nope, it should be “X” if it matched.

$1 # => “G”

just to double check

$1 if /re(.)ex/ # => “X”

So, regex aren’t nil or false, and are thus truthy. But when you throw a
regex literal in the conditional, it does some implicit operations and
doesn’t pass the regex straight on through to the conditional.

On Mon, Apr 4, 2011 at 5:08 AM, John F. [email protected]
wrote:

@first_name ||= ‘’

No. That is equivalent to:

@first_name || @first_name = “”

which is not the same as

@first_name = @first_name || “”

See also

irb(main):004:0> x=Object.new
=> #Object:0x10924b1c
irb(main):005:0> def x. puts “get”;@x;end
=> nil
irb(main):006:0> def x.[]=(k,v) puts “put”;@x=v;end
=> nil
irb(main):007:0> x[1] ||= 2
get
put
=> 2
irb(main):008:0> x[1] ||= 2
get
=> 2

This has been discussed at lengths here in the past. You should be
able to find plenty of evidence. :slight_smile:

Kind regards

robert

On Mon, Apr 4, 2011 at 7:12 PM, 7stud – [email protected] wrote:

Makes sense, and passed the test I constructed to invalidate it:
lhs = rhs || “pass”
lhs # =>

~> -:1:in <main>': undefined local variable or method rhs’ for

main:Object (NameError)

I probably never figured that out because it depends on the variable
type,
for example:
lhs = @rhs || “pass” # => “pass”
and
lhs = $rhs || “pass” # => “pass”

Good thought. I’m honestly surprised that works! I guess it must add x
to
the symbol table at parse time.

Josh C. wrote in post #990762:

  1. For some reason that I don’t know (probably interpreter magic) an
    uninitialized variable can be referenced in a boolean equation and it
    will
    evaluate to nil.

That effect is not limited to boolean expressions.

I think the story goes something like this: when the parser (i.e. the
thing that looks over your code for, among other things, syntax errors
before your code is executed) sees any ‘name =’ expression, then name
gets entered into the symbol table. Thereafter, you will no longer get
an exception when referencing the variable. In your code, the parser
sees ‘first_name =’, so first_name
is entered into the symbol table, and later when ruby executes your
code, the expression on the right hand side of the equals sign is
executed.

Here is another example of how that works:

if 1 > 10
x = ‘hello’ #never executes
end

puts x #=> nil
puts y #=> undefined local variable or method `y’
#for main:Object (NameError)

The only difference between x and y is that the parser saw ‘x =’
somewhere in the code and reserved space for a variable called x. So as
far as ruby is concerned, the variable x exists, but it has not yet been
assigned any value.

On Tue, Apr 05, 2011 at 12:30:47PM +0900, Josh C. wrote:

puts y #=> undefined local variable or method `y’
#for main:Object (NameError)

Good thought. I’m honestly surprised that works! I guess it must add x
to the symbol table at parse time.

Is that something we should be able to depend on, though – or just an
accident of implementation?

On Tue, Apr 5, 2011 at 4:35 PM, Chad P. [email protected] wrote:

puts x #=> nil
puts y #=> undefined local variable or method `y’
#for main:Object (NameError)

Good thought. I’m honestly surprised that works! I guess it must add x
to the symbol table at parse time.

Is that something we should be able to depend on, though – or just an
accident of implementation?

I think it’s a language feature. From the line where an assignment to
a identifier is found this identifier denotes a local variable -
whether the code is actually executed does not matter. This is only
about syntactical order. Consider

$ ruby19 -e ‘puts(x) if x=1’
-e:1: warning: found = in conditional, should be ==
-e:1:in <main>': undefined local variable or method x’ for
main:Object (NameError)
$ ruby19 -e ‘x=1;puts(x) if x’
1
$

Kind regards

robert

Josh C. wrote in post #990917:

I probably never figured that out because it depends on the variable
type,
for example:
lhs = @rhs || “pass” # => “pass”
and
lhs = $rhs || “pass” # => “pass”

Remember, by rule instance variables and global variables have a default
value of nil (that’s in the Pickaxe somewhere), where local variables
don’t have a default value (subject to the parser exception mentioned
above).

On Mon, Apr 4, 2011 at 7:12 PM, 7stud – [email protected] wrote:

Actually, I was thinking about it, and this contradicts that a||=b
expands
to a||a=b

undefined1 ||= :defined
undefined1 # => :defined

undefined2 = ( undefined2 || :defined )
undefined2 # => :defined

undefined3 || ( undefined3 = :defined )
undefined3 # =>

~> -:7:in <main>': undefined local variable or method undefined3’

for
main:Object (NameError)

Josh C. wrote in post #990806:

If you put a regex in a
variable, it treats it as a boolean “is it an object?” and behaves as I
stated previously. But if you put it in a literal, it plays Perl and
checks
to see if it matches against $_

Yes, this is a very ugly inheritance from Perl. Check out the flip-flop
operator too :slight_smile:

On Wed, Apr 06, 2011 at 04:00:08PM +0900, Jess Gabriel y Galn wrote:

9.1.2 References to local variables

. . .

5 variable of left-hand-side

. . .

As you can see, number 5 (variable of LHS) covers the case we are
discussing here.

Thanks for finding that.

On Tue, Apr 5, 2011 at 4:35 PM, Chad P. [email protected] wrote:

puts x #=> nil
puts y #=> undefined local variable or method `y’
#for main:Object (NameError)

Good thought. I’m honestly surprised that works! I guess it must add x
to the symbol table at parse time.

Is that something we should be able to depend on, though – or just an
accident of implementation?

I think it’s a language feature. In the Ruby Draft Specification
(http://ruby-std.netlab.jp/draft_spec/draft_ruby_spec-20091201-hl.pdf)
you can read this:

9.1.2 References to local variables
An occurrence of a local-variable-identifier can be a reference to a
local variable or a method
invocation. In order to determine whether the occurrence of a
local-variable-identifier is a
reference to a local variable or a method invocation, before the
evaluation of a local variable
scope, the scope is scanned sequentially for local-variable-identifier
s.
For each occurrence of a local-variable-identifier I, take the following
steps:
a) If I occurs in one of the forms below, I is a reference to a local
variable.
1 mandatory-parameter
2 optional-parameter-name
3 array-parameter-name
4 block-parameter-name
5 variable of left-hand-side
6 variable of single-variable-assignment-expression
7 variable of single-variable-assignment-statement
8 variable of abbreviated-variable-assignment-expression
9 variable of abbreviated-variable-assignment-statement

As you can see, number 5 (variable of LHS) covers the case we are
discussing here.

Jesus.