In Ruby, how does puts _|_ work? - ruby

I am confused with how puts _|_ works in Ruby. If you type in a variable and then call that statement
3
puts _|_
you get the name of the variable followed by nil
3
=> nil
However, if you type it again, you get false
puts _|_
=> false
It doesn't seem like one of those Perl-like variables that begin with a dollar sign.
What in the world does this weird symbol mean and how does it work?

The underscore in a console (IRB or pry) stands for the result of the previous command. So
3
=> 3
puts _|_
3
=> nil
Here the above puts statement becomes equivalent to
puts 3 <bit-wise or> 3
which puts 3|3 equals puts 3.
Since puts returns nil, when you repeat the puts _|_ it becomes
puts nil|nil
... which is puts false.

In ruby _ is a valid identifier.
In IRB _ contains the value of the last expression.
2.1.5 :001 > 100
=> 100
2.1.5 :002 > _
=> 100

_ is a ruby special variable, it is used to get the result of the previous expression.
irb(main):030:0> 3
=> 3
irb(main):031:0> _
=> 3
irb(main):032:0> _.to_s
=> "3"
irb(main):033:0> _
=> "3"
A ruby variable whose name begins with a lowercase letter (a-z) or underscore (_) is a local variable or method invocation. Uninitialized instance variables have a value of nil.
irb(main):001:0> _
=> nil
irb(main):002:0> _ | _
=> false
irb(main):003:0> nil | nil
=> false

_ is a ruby special variable, this variable stores out put of the previous expression/command, so when you do:
1.9.3-p0 :043 > 3
=> 3
'_' contains the value 3, because return value of previous expression is 3. When you use puts as below:
1.9.3-p0 :045 > puts _|_
3
=> nil
its return value is nil.Next time when you execute the | as below:
1.9.3-p0 :049 > _|_
=> false
it returns false because it is same as below expression:
1.9.3-p0 :050 > nil|nil
=> false
that is why puts | returns false.

Related

Strange behavior with '_' (underscore) in Ruby

Just curious about it.
If you open the IRB and type _, you'll get nil as response:
irb(main):001:0> _
=> nil
And you can modify its value:
irb(main):002:0> _ = 'some value'
irb(main):003:0> _
=> "some value"
But if you create a new variable with _, its value is modified:
irb(main):004:0> foo_bar = 'other value'
irb(main):005:0> _
=> "other value"
Why? Is this a design decision?
irb uses _ to refer to the value of last calculated expression. So you will see _ changed even if you don't use it in the previous line :)
Within irb, _ returns the result of the previous operation. So on opening a new irb session _ will equal nil as there was no previous operation
2.0.0p353 :001 > 4
=> 4
2.0.0p353 :002 > 3 + _
=> 7

Why a dangerous method doesn't work with a character element of String in Ruby?

When I apply the upcase! method I get:
a="hello"
a.upcase!
a # Shows "HELLO"
But in this other case:
b="hello"
b[0].upcase!
b[0] # Shows h
b # Shows hello
I don't understand why the upcase! applied to b[0] doesn't have any efect.
b[0] returns a new String every time. Check out the object id:
b = 'hello'
# => "hello"
b[0].object_id
# => 1640520
b[0].object_id
# => 25290780
b[0].object_id
# => 24940620
When you are selecting an individual character in a string, you're not referencing the specific character, you're calling a accessor/mutator function which performs the evaluation:
2.0.0-p643 :001 > hello = "ruby"
=> "ruby"
2.0.0-p643 :002 > hello[0] = "R"
=> "R"
2.0.0-p643 :003 > hello
=> "Ruby"
In the case when you run a dangerous method, the value is requested by the accessor, then it's manipulated and the new variable is updated, but because there is no longer a connection between the character and the string, it will not update the reference.
2.0.0-p643 :004 > hello = "ruby"
=> "ruby"
2.0.0-p643 :005 > hello[0].upcase!
=> "R"
2.0.0-p643 :006 > hello
=> "ruby"

Print memory address for Ruby array

irb> class A; end
=> nil
irb> a=A.new
=> "#<A:0x3094638>"
irb> a.inspect
=> "#<A:0x3094638>"
irb> b=[]
=> []
irb> b.inspect
=> "[]"
How to get memory address of an array object?
Use the method Object#object_id.
Returns an integer identifier for obj. The same number will be returned on all calls to id for a given object, and no two active objects will share an id. #object_id is a different concept from the :name notation, which returns the symbol id of name.
Example :-
Arup-iMac:arup_ruby $ irb
2.1.2 :001 > s = "I am a string"
=> "I am a string"
2.1.2 :002 > obj_id = s.object_id
=> 2156122060
2.1.2 :003 > ObjectSpace._id2ref obj_id
=> "I am a string"
2.1.2 :004 >

Regular expression for only 2 letters

I need to create regular expression for 2 and only 2 letters. I understood it has to be the following /[a-z]{2}/i, but it matches any string with 2 or more letters. Here is what I get:
my_reg_exp = /[a-z]{2}/i
my_reg_exp.match('aa') # => #<MatchData "aa">
my_reg_exp.match('AA') # => #<MatchData "AA">
my_reg_exp.match('a') # => nil
my_reg_exp.match('aaa') # => #<MatchData "aa">
Any suggestion?
You can add the anchors like this:
my_reg_exp = /^[a-z]{2}$/i
Test:
my_reg_exp.match('aaa')
#=> nil
my_reg_exp.match('aa')
#=> #<MatchData "aa">
Hao's solution matches isn't locale sensitive. If this is important for your use case:
/\a[[:alpha:]]{2}\z/
2.0.0-p451 :005 > 'aba' =~ /\A[[:alpha:]]{2}\Z/
=> nil
2.0.0-p451 :006 > 'ab' =~ /\A[[:alpha:]]{2}\Z/
=> 0
2.0.0-p451 :007 > 'xy' =~ /\A[[:alpha:]]{2}\Z/
=> 0
2.0.0-p451 :008 > 'zxy' =~ /\A[[:alpha:]]{2}\Z/
=> nil
Per usual, if you need further assistance, leave a comment.
You can use /\b[a-z]{2}\b/i to match a two-letter string. /b Matches a word-break.
This means you can scan a string to find all occurrences:
'Foo is a bar'.scan(/\b[a-z]{2}\b/i) #=> ["is"]
Or find the first match in a string using:
'a bc def'[/\b[a-z]{2}\b/i] # => "bc"

Why is String#index returning nil here?

On the last two lines:
$ ruby -v
ruby 1.9.1p378 (2010-01-10 revision 26273) [i386-darwin10]
$ irb
irb(main):001:0> def t(str)
irb(main):002:1> str.index str
irb(main):003:1> end
=> nil
irb(main):004:0> t 'abc'
=> 0
irb(main):005:0> t "\x01\x11\xfe"
=> nil
irb(main):006:0> t "\x01\x11\xfe".force_encoding(Encoding::UTF_8)
=> nil
Why does str.index str return nil?
"\x01\x11\xfe" is not valid UTF8.
If you call t "\x01\x11\xfe".force_encoding(Encoding::BINARY), you'll get the expected 0.
The behavior is different on my older Ruby:
$ ruby -v ; irb
ruby 1.8.7 (2010-01-10 patchlevel 249) [x86_64-linux]
irb(main):001:0> def t(str)
irb(main):002:1> str.index str
irb(main):003:1> end
=> nil
irb(main):004:0> t 'abc'
=> 0
irb(main):005:0> t "\x01\x11\xfe"
=> 0
I suspect it has something to do with the difference between single-quotes and double-quotes with string literals in ruby:
ruby-1.9.1-p378 > def t(str) ; str.index(str) ; end
=> nil
ruby-1.9.1-p378 > t 'abc'
=> 0
ruby-1.9.1-p378 > t "\x01\x11\xfe"
=> nil
ruby-1.9.1-p378 > t '\x01\x11\xfe'
=> 0
The short answer is that using single-quotes does minimal text processing, but double-quotes allows interpolation, character escaping, and a few other things.
Some examples:
#interpolation
ruby-1.9.1-p378 > x = 5 ; 'number: #{x}'
=> "number: \#{x}"
ruby-1.9.1-p378 > x = 5 ; "number: #{x}"
=> "number: 5"
#character escaping
ruby-1.9.1-p378 > puts 'tab\tseparated'
tab\tseparated
=> nil
ruby-1.9.1-p378 > puts "tab\tseparated"
tab separated
=> nil
#hex characters
ruby-1.9.1-p378 > puts '\x01\x11\xfe'
\x01\x11\xfe
=> nil
ruby-1.9.1-p378 > puts "\x01\x11\xfe"
�
=> nil
I'm sure someone can explain better why this happens, this is just what I've experienced in my rubying.

Resources