Couldn't understand the difference between `puts{}.class` and `puts({}.class)` - ruby

As the anonymous block and hash block looks like approximately same. I was doing kind of playing with it. And doing do I reached to some serious observations as below:
{}.class
#=> Hash
Okay,It's cool. empty block is considered as Hash.
print{}.class
#=> NilClass
puts {}.class
#=> NilClass
Now why the above code showing the same as NilClass,but the below code shows the Hash again ?
puts ({}.class)
#Hash
#=> nil
print({}.class)
#Hash=> nil
Could anyone help me here to understand that what's going one above?
I completely disagree with the point of #Lindydancer
How would you explain the below lines:
print {}.class
#NilClass
print [].class
#Array=> nil
print (1..2).class
#Range=> nil
Why not the same with the below print [].class and print (1..2).class?
EDIT
When ambiguity happens with local variable and method call, Ruby throws an error about the fact as below :
name
#NameError: undefined local variable or method `name' for main:Object
# from (irb):1
# from C:/Ruby193/bin/irb:12:in `<main>'
Now not the same happens with {} (as there is also an ambiguity between empty code block or Hash block). As IRB also here not sure if it's a empty block or Hash. Then why the error didn't throw up when IRB encountered print {}.class or {}.class?

The precedence rules of ruby makes print{}.class interpreted as (print{}).class. As print apparently returns a nil the class method returns #NilClass.
EDIT: As been discussed on other answers and in the updates to the question, print{} it of course interpreted as calling print with a block, not a hash. However, this is still about precedence as {} binds stronger than [] and (1..2) (and stronger than do ... end for that matter).

{} in this case is recognized as block passed to print, while [] unambiguously means empty array.
print {}.class # => NilClass
print do;end.class # => NilClass

You are running into some nuances of Ruby, where characters mean different things depending on context. How the source code is interpreted follows rules, one of which is that {} is a closure block if it follows a method call, and otherwise a Hash constructor.
It's common throughout the language to see characters mean different things depending on context or position within the statement.
Examples:
Parens () used for method call or for precedence
print(1..5).class => NilClass
print (1..5).class => Range <returns nil>
Square brackets [] used to call :[] method or for Array
print[].class => NoMethodError: undefined method `[]' for nil:NilClass
print([].class) => Array <returns nil>
Asterisk * used for multiplication or splatting
1 * 5 => 5
[*1..5] => [1, 2, 3, 4, 5]
Ampersand & used for symbol -> proc or logical and
0 & 1 => 0
[1, 2, 3].map(&:to_s) => ["1", "2", "3"]
Or in your case, braces used for block closures or for a hash
... hope it makes sense now ...

Related

Why do I get this Error in ruby: block in find_word_lengths': undefined method `[]=' for 3:Integer (NoMethodError)

the following code return this error:
block in find_word_lengths': undefined method `[]=' for 3:Integer (NoMethodError)
animals = ['cat', 'horse', 'rabbit', 'deer']
def find_word_lengths(word_list)
word_list.reduce(Hash.new()) do |result, animal|
result[animal] = animal.length
end
end
puts find_word_lengths(animals)
The return value of the block is the accumulator value for the next iteration. That is how a fold works.
Assignments in Ruby evaluate to the right-hand side. So, in the first iteration of reduce, the block evaluates to 3 (the length of 'cat'). Which means that in the second iteration of reduce, result is 3, and you are essentially running
3['horse'] = 5
# which is equivalent to
3.[]=('horse', 5)
Which is why you are getting the error message that the Integer 3 does not respond to the message []=.
So, you need to make sure that your block always returns the value that you want to use for the accumulator in the next iteration. Something like this:
word_list.reduce(Hash.new()) do |result, animal|
result.tap {|result| result[animal] = animal.length }
end
This would be the obvious solution, although somewhat cheating.
word_list.reduce(Hash.new()) do |result, animal|
result.merge(animal => animal.length)
end
Would be more idiomatic.
However, when you want to fold into a mutable object, it makes more sense to use Enumerable#each_with_object instead of Enumerable#reduce. each_with_object ignores the result of the block, and simply passes the same object every time. Note that somewhat confusingly, the order of the block parameters is swapped in each_with_object compared to reduce.
word_list.each_with_object(Hash.new()) do |animal, result|
result[animal] = animal.length
end
But I guess the most idiomatic solution would be something like this:
word_list.map {|word| [word, word.length] }.to_h
By the way, in Ruby, it is idiomatic to leave out the parentheses for the argument list if you are not passing any arguments, so Hash.new() should be Hash.new instead. Even more important than being idiomatic is to be consistent – confusingly, you leave out the parentheses for animal.length, but not for Hash.new
Even more idiomatically, you would use the Hash literal notation instead of the Hash::new method, i.e. you should use {} instead of Hash.new.

Ruby: Safe-navigation operator, undefined method `call`

I am trying to compare a number literal with the return value of a function that could return nil or a numeric. Consider this:
def unreliable
[nil, 42].sample
end
unreliable > 10
This will blow up 50% of the time with NoMethodError: undefined method '>' for nil:NilClass. So I tried this:
unreliable&.(:>, 10)
That approach does the nil guarding I expect, but I get this when unreliable returns 42:
NoMethodError: undefined method `call' for 42:Fixnum
I suspect this has to do with the quirks of allowing only one instance to exist for each Numeric, see here. And I know I can do this:
foo = unreliable
foo && foo > 10
But is there a way to use the safe navigation operator with a numeric and :>, :<, :==, :+, :-, :/, :*, etc?
Edit: The focus on Numeric in my question is a red herring. See #Jörg's answer. I was confusing Rails's try syntax with the safe-navigation operator's syntax.
This works fine in Ruby 2.3+ :
unreliable&.> 10
For example :
[-5, 0, nil, 5].each do |unreliable|
p unreliable&.> 0
end
# false
# false
# nil
# true
The way you tried it, Ruby expects unreliable to be a callable object such as a Proc :
unreliable = Proc.new{ |*params| puts "unreliable has been called with #{params}" }
unreliable&.(:>, 10)
# unreliable has been called with [:>, 10]
unreliable.call(:>, 10)
# unreliable has been called with [:>, 10]
unreliable&.call(:>, 10)
# unreliable has been called with [:>, 10]
unreliable[:>, 10]
# unreliable has been called with [:>, 10]
With the safe-navigation operator, there's no need to put parens and the method should be a method name, not a symbol (Rails' try expects a symbol).
I suspect this has to do with the quirks of allowing only one instance to exist for each Numeric
No, this has nothing to do with that at all.
foo.(bar)
is syntactic sugar for
foo.call(bar)
Ergo,
foo&.(bar)
is syntactic sugar for
foo&.call(bar)
So, your code:
unreliable&.(:>, 10)
is syntactic sugar for
unreliable&.call(:>, 10)
I'm not sure who told you that the safe-navigation operator takes the message as a symbol argument. The whole point of the safe-navigation operator is that you only have trivial syntactic overhead by adding a single character, the & in front of the ., and the expression is otherwise unchanged.
So,
unreliable > 10
which is the same as
unreliable.>(10)
simply becomes
unreliable&.>(10)

Why do you have to specify 2 arguments explicitly to curry :>

Consider this, which works fine:
:>.to_proc.curry(2)[9][8] #=> true, because 9 > 8
However, even though > is a binary operator, the above won't work without the arity specified:
:>.to_proc.curry[9][8] #=> ArgumentError: wrong number of arguments (0 for 1)
Why aren't the two equivalent?
Note: I specifically want to create the intermediate curried function with one arg supplied, and then call then call that with the 2nd arg.
curry has to know the arity of the proc passed in, right?
:<.to_proc.arity # => -1
Negative values from arity are confusing, but basically mean 'variable number of arguments' one way or another.
Compare to:
less_than = lambda {|a, b| a < b}
less_than.arity # => 2
When you create a lambda saying it takes two arguments, it knows it takes two arguments, and will work fine with that style of calling #curry.
less_than.curry[9][8] # => false, no problem!
But when you use the symbol #to_proc trick, it's just got a symbol to go on, it has no idea how many arguments it takes. While I don't think < is actually an ordinary method in ruby, I think you're right it neccessarily takes two args, the Symbol#to_proc thing is a general purpose method that works on any method name, it has no idea how many args the method should take, so defines the proc with variable arguments.
I don't read C well enough to follow the MRI implementation, but I assume Symbol#to_proc defines a proc with variable arguments. The more typical use of Symbol#to_proc, of course, is for a no-argument methods. You can for instance do this with it if you want:
hello_proc = :hello.to_proc
class SomeClass
def hello(name = nil)
puts "Hello, #{name}!"
end
end
obj = SomeClass.new
obj.hello #=> "Hello, !"
obj.hello("jrochkind") #=> "Hello, jrochkind!"
obj.hello("jrochkind", "another")
# => ArgumentError: wrong number of arguments calling `hello` (2 for 1)
hello_proc.call(obj) # => "Hello, !"
hello_proc.call(obj, "jrochkind") # => "Hello, jrochkind!"
hello_proc.call(obj, "jrochkind", "another")
# => ArgumentError: wrong number of arguments calling `hello` (2 for 1)
hello_proc.call("Some string")
# => NoMethodError: undefined method `hello' for "Some string":String
Note I did hello_proc = :hello.to_proc before I even defined SomeClass. The Symbol#to_proc mechanism creates a variable arity proc, that knows nothing about how or where or on what class it will be called, it creates a proc that can be called on any class at all, and can be used with any number of arguments.
If it were defined in ruby instead of C, it would look something like this:
class Symbol
def to_proc
method_name = self
proc {|receiver, *other_args| receiver.send(method_name, *other_args) }
end
end
I think it is because Symbol#to_proc creates a proc with one argument. When turned into a proc, :> does not look like:
->x, y{...}
but it looks like:
->x{...}
with the requirement of the original single argument of > somehow tucked inside the proc body (notice that > is not a method that takes two arguments, it is a method called on one receiver with one argument). In fact,
:>.to_proc.arity # => -1
->x, y{}.arity # => 2
which means that applying curry to it without argument would only have a trivial effect; it takes a proc with one parameter, and returns itself. By explicitly specifying 2, it does something non-trivial. For comparison, consider join:
:join.to_proc.arity # => -1
:join.to_proc.call(["x", "y"]) # => "xy"
:join.to_proc.curry.call(["x", "y"]) # => "xy"
Notice that providing a single argument after Currying :join already evaluates the whole method.
#jrochkind's answer does a great job of explaining why :>.to_proc.curry doesn't have the behavior you want. I wanted to mention, though, that there's a solution to this part of your question:
I specifically want to create the intermediate curried function with one arg supplied, and then call then call that with the 2nd arg.
The solution is Object#method. Instead of this:
nine_is_greater_than = :>.to_proc.curry[9]
nine_is_greater_than[8]
#=> ArgumentError: wrong number of arguments (0 for 1)
...do this:
nine_is_greater_than = 9.method(:>)
nine_is_greater_than[8]
# => true
Object#method returns a Method object, which acts just like a Proc: it responds to call, [], and even (as of Ruby 2.2) curry. However, if you need a real proc (or want to use curry with Ruby < 2.2) you can also call to_proc on it (or use &, the to_proc operator):
[ 1, 4, 8, 10, 20, 30 ].map(&nine_is_greater_than)
# => [ true, true, true, false, false, false ]

Understanding strange output in multidimensional array

I am new to ruby and I was trying to iterate over a 2d array. I made a mistake in my code. From that mistake, I noticed some unexpected output.
s = [["ham", "swiss"], ["turkey", "cheddar"], ["roast beef", "gruyere"]]
i = 0;
s.each{
|array| so = array[i] # pin
puts so[i]
}
Due to #pin, if i = 0, output is h t r. i = 1 gives w h r. i > 1 gives an error:
C:/Ruby.rb in `block in <main>': undefined method `[]' for nil:NilClass (NoMethodError)
from C:/Ruby.rb:3:in `each'
from C:/Ruby.rb:3:in `<main>'
If I use |array| so = array # pin, then my code does not produce strange output. I'll just fix the remaining stuff to make my code iterate for all values that 'i' can have.
Please explain this.
PS: Working code is here
s = [["ham", "swiss"], ["turkey", "cheddar"], ["roast beef", "gruyere"]]
s.each{
|array| so = array
array.each{
|str| puts str
}
}
For each type of sandwich, when i is 0, so is the 1st element, which is the meat. so[0] is the first letter of the meat.
When i is 1, which is the 2nd element, which is the cheese. so[1] is the second letter of the cheese.
When i is 3, there is no third component to the sandwich. so so is nil. so[2] is asking for the nil[2].
nil is a class, like everything in ruby. But nil does not implement the [] method, as arrays and other classes that implement the Enumerable module do.
Since nil does not support the [] method, then you get the undefined method error.
Even operations that are built into other languages, like +, [], and == are methods that can be overridden in Ruby.
To understand exactly what's happening, try this bit of code:
class NilClass
def [] (i)
nil
end
end
Executing that will open up the existing NilClass, and add a method called []. Then you can do nil[1] and it will return nil. Changing an existing class like this is known as monkey patching in the Ruby world.
When you ask for so[2] you are actually asking for the third element, and if it doesn't exist, you'll get an error.
I recommend structuring your blocks like so:
s.each do |pair|
puts pair
end
Note the do/end instead of {} and the placement of the iteration variable inline with the each. Also note that this is equivalent to your "working code" so you don't need the extra iterator in this case.

"for" vs "each" in Ruby

I just had a quick question regarding loops in Ruby. Is there a difference between these two ways of iterating through a collection?
# way 1
#collection.each do |item|
# do whatever
end
# way 2
for item in #collection
# do whatever
end
Just wondering if these are exactly the same or if maybe there's a subtle difference (possibly when #collection is nil).
This is the only difference:
each:
irb> [1,2,3].each { |x| }
=> [1, 2, 3]
irb> x
NameError: undefined local variable or method `x' for main:Object
from (irb):2
from :0
for:
irb> for x in [1,2,3]; end
=> [1, 2, 3]
irb> x
=> 3
With the for loop, the iterator variable still lives after the block is done. With the each loop, it doesn't, unless it was already defined as a local variable before the loop started.
Other than that, for is just syntax sugar for the each method.
When #collection is nil both loops throw an exception:
Exception: undefined local variable or method `#collection' for main:Object
See "The Evils of the For Loop" for a good explanation (there's one small difference considering variable scoping).
Using each is considered more idiomatic use of Ruby.
Your first example,
#collection.each do |item|
# do whatever
end
is more idiomatic. While Ruby supports looping constructs like for and while, the block syntax is generally preferred.
Another subtle difference is that any variable you declare within a for loop will be available outside the loop, whereas those within an iterator block are effectively private.
One more different..
number = ["one", "two", "three"]
=> ["one", "two", "three"]
loop1 = []
loop2 = []
number.each do |c|
loop1 << Proc.new { puts c }
end
=> ["one", "two", "three"]
for c in number
loop2 << Proc.new { puts c }
end
=> ["one", "two", "three"]
loop1[1].call
two
=> nil
loop2[1].call
three
=> nil
source: http://paulphilippov.com/articles/enumerable-each-vs-for-loops-in-ruby
for more clear: http://www.ruby-forum.com/topic/179264#784884
Never ever use for it may cause almost untraceable bugs.
Don't be fooled, this is not about idiomatic code or style issues. Ruby's implementation of for has a serious flaw and should not be used.
Here is an example where for introduces a bug,
class Library
def initialize
#ary = []
end
def method_with_block(&block)
#ary << block
end
def method_that_uses_these_blocks
#ary.map(&:call)
end
end
lib = Library.new
for n in %w{foo bar quz}
lib.method_with_block { n }
end
puts lib.method_that_uses_these_blocks
Prints
quz
quz
quz
Using %w{foo bar quz}.each { |n| ... } prints
foo
bar
quz
Why?
In a for loop the variable n is defined once and only and then that one definition is use for all iterations. Hence each blocks refer to the same n which has a value of quz by the time the loop ends. Bug!
In an each loop a fresh variable n is defined for each iteration, for example above the variable n is defined three separate times. Hence each block refer to a separate n with the correct values.
It looks like there is no difference, for uses each underneath.
$ irb
>> for x in nil
>> puts x
>> end
NoMethodError: undefined method `each' for nil:NilClass
from (irb):1
>> nil.each {|x| puts x}
NoMethodError: undefined method `each' for nil:NilClass
from (irb):4
Like Bayard says, each is more idiomatic. It hides more from you and doesn't require special language features.
Per Telemachus's Comment
for .. in .. sets the iterator outside the scope of the loop, so
for a in [1,2]
puts a
end
leaves a defined after the loop is finished. Where as each doesn't. Which is another reason in favor of using each, because the temp variable lives a shorter period.
(1..4).each { |i|
a = 9 if i==3
puts a
}
#nil
#nil
#9
#nil
for i in 1..4
a = 9 if i==3
puts a
end
#nil
#nil
#9
#9
In 'for' loop, local variable is still lives after each loop. In 'each' loop, local variable refreshes after each loop.
As far as I know, using blocks instead of in-language control structures is more idiomatic.
I just want to make a specific point about the for in loop in Ruby. It might seem like a construct similar to other languages, but in fact it is an expression like every other looping construct in Ruby. In fact, the for in works with Enumerable objects just as the each iterator.
The collection passed to for in can be any object that has an each iterator method. Arrays and hashes define the each method, and many other Ruby objects do, too. The for/in loop calls the each method of the specified object. As that iterator yields values, the for loop assigns each value (or each set of values) to the specified variable (or variables) and then executes the code in body.
This is a silly example, but illustrates the point that the for in loop works with ANY object that has an each method, just like how the each iterator does:
class Apple
TYPES = %w(red green yellow)
def each
yield TYPES.pop until TYPES.empty?
end
end
a = Apple.new
for i in a do
puts i
end
yellow
green
red
=> nil
And now the each iterator:
a = Apple.new
a.each do |i|
puts i
end
yellow
green
red
=> nil
As you can see, both are responding to the each method which yields values back to the block. As everyone here stated, it is definitely preferable to use the each iterator over the for in loop. I just wanted to drive home the point that there is nothing magical about the for in loop. It is an expression that invokes the each method of a collection and then passes it to its block of code. Hence, it is a very rare case you would need to use for in. Use the each iterator almost always (with the added benefit of block scope).

Resources