Ruby puts command in modules returning nil - ruby

i am working though LearnTocodethehardway.com http://ruby.learncodethehardway.org/book/ex25.html
On ex25. In the example there is a module that has a bunch of methods that return or print values. The Print_last_word method when supplied with an array of strings just puts nil. it does this even in his example output. My question would then be why?

To be precise, it doesn't puts nil - it puts the last word and returns nil. Here's the example output:
>> Ex25.print_last_word(words)
wait. # <- this is the output
=> nil # <- this is the return value
puts always returns nil.
UPDATE
There seems to be a bug in print_first_word:
module Ex25
def Ex25.print_first_word(words)
word = words.pop(0)
puts word
end
end
Ex25.print_first_word(["foo", "bar", "baz"])
#=> nil
This is because ["foo", "bar", "baz"].pop(0) returns an empty array and puts [] just returns nil without printing anything.
A working implementation (in the exercise's style) could look like this:
module Ex25
def Ex25.print_first_word(words)
word = words.shift
puts word
end
end

To make it more easy to understand:
"puts" never is used for its return value. It is used for its side effect if you wanted a method that would return a word, you would then do something with that word.
words = ["apple", "cucumber", "apple"]
def give_me_first_word(array_of_words)
array_of_words.first
end
variable_to_be_used_later = give_me_first_word(words)
This function would return "apple"(and in this case the variable would be assigned "apple"), but it would puts nothing to the screen. This value would then be used in another program or function.
If you puts a value, you would then not need to return it to any other program as it's already served its purpose. It's actually intuitive because if puts also returned the value, it would be doing two things. The counterpart to "puts" would be "return" that simply returns the value and does not display it to the screen.

Related

Why does `puts {}.class.name` return nothing in Ruby?

I've tried this with other classes and they return things. Just this one doesn't.
puts ''.class.name # String
puts 1.class.name # Integer
puts [].class.name # Array
puts {}.class.name
but {}.class.name just returns blank.
Because puts {} passes a block.
Any method can take a block.
puts {}.class.name is really (puts {}).class.name. puts {} ignores the block and prints a newline. It returns nil. class.name is called on nil so the return value is NilClass. But that doesn't get passed to puts so it's not printed.
We can see it in IRB.
> puts {}.class.name
=> "NilClass"
Use parens to clarify. puts({}.class.name).
It's because {} is interpreted as a block sent to puts.
class.name is executed when puts returns, and the value is discarded.

What's the difference between `puts` and `return` result?

When I run the following code:
class GermanShepard
attr_accessor :name
def bark
puts "Loud Bark"
end
end
max = GermanShepard.new
max.name = "Max"
puts "#{max.name} goes #{max.bark}"
the result is:
Loud Bark
Max goes
When I change puts to return at the GermanShepard. It gives:
Max goes Loud Bark
I don't understand the difference between the two command in the class.
Expression
In most languages, return in a method means giving a value to the caller.
In Ruby, everything is an expression. In an essence, the last line of a method is automatically called with return. As an example, the following methods are equivalent:
def bark_a
'Woof!'
end
def bark_b
return 'Woof!'
end
However, some methods may not be returning anything.
def bark_c
end
In this case, ruby is actually returning a nil object. An example would be the
puts method. The puts method simply displays whatever you've given it.
So in your example,
def bark
puts "Loud Bark"
end
is actually doing 2 things.
It's calling the puts method (displaying Loud Bark to the terminal screen)
then it's giving a nil value back to the method caller.
You can try running puts nil and see what's printed out!
"#{}"
Calling #{} in ruby is called interpolation, which is basically putting the variables together in their closest string representation value. The following statements are roughly equivalent:
puts "One plus one equals #{1 + 1}"
puts "One plus one equals " + (1 + 1).to_s
Your example
With all the information above, we can now go through your example step-by-step.
The line puts "#{max.name} goes #{max.bark}" can be separated into a few steps
Calls the name method
The value returned is converted into the closest string representation (In this case we don't need to do anything since name is already a string)
The value is then saved to a temporary variable
At this point, our temporary variable is Max goes.
Calls the bark method
The line puts "Loud Bark" gets executed since we're calling it in the bark method.
Terminal(console) displays "Loud Bark"
Since the puts method returns a nil value, the bark method is also going to return a nil value because it's the last line of the bark method. (Read "Expression" above)
nil is then converted to the closest string representation (which is "")
It is then saved to a temporary variable
The temporary variable is now Max goes
Now, the temporary variable is passed into the puts method, and the terminal(console) displays "Max goes "
Program finishes
Therefore, your example prints out
Loud Bark
Max goes
However, if we change the puts inside the bark method to return,
Step 6 will not happen.
Instead of returning a nil value in step 7, it will return "Load bark"
Step 8 will not happen since "Loud bark" already a string value
and the temporary value after step 9 will become Max goes Loud bark
Hope this helps!
Ray's answer is probably correct, but since it is too verbose (and I didn't even feel like reading it), I will post a concise answer.
There are two things to have in mind.
All arguments passed to a method are evaluated prior to the method call.
All methods in Ruby have a return value. In addition, some methods have side effect, an example of which is to output on the terminal. In any case, returning a value is done after a method has done all its side effects.
With your code as is, the argument of puts in
puts "#{max.name} goes #{max.bark}"
is first evaluated. In order to do so, max.bark (among other things like max.name) would have to be evaluated in advance. The method bark prints "Loud Bark", then returns nil. So the argument mentioned above becomes "#{"Max"} goes #{nil}", and eventually to "Max goes ". That is printed after "Loud Bark".
When you change the puts in the method to return, the method bark will have no side effect, and returns "Loud Bark"; that is the function of return (and by the way, return is not a method but is a keyword). So the argument mentioned above becomes "#{"Max"} goes #{"Loud Bark"}", and eventually to "Max goes Loud Bark". That would be the only thing printed.
puts(string) in ruby writes the string value into $stdout. For example if you run ruby console in terminal, string will be written into your terminal. At the same time every method in ruby returns something and method puts returns nil. So, when we want to interpolate string like "Hello #{some_method}" it will interpolate a returning value of some_method, in case of puts it will interpolate nil value.
Loud Bark # output of max.bark method
Max goes # output of last puts
puts "Loud Bark" # => returns nil
return "Loud Bark" # => returns "Loud Bark"

Why does Kernel#p duplicate my text on standard output?

Look at this code :
def hello
p "Hey!"
end
p hello
the output will be:
"Hey!"
"Hey!"
=> "Hey!"
And so here is my conclusion: puts itself returns the text which is going to be sent in output in Ruby code, else it wouldn't print "Hey!" again. What is happening while printing the string? If puts doesn't send it to standard output directly, who is responsible for it and how?
All Methods Return a Value
In Ruby, almost everything returns a value, even if that value is nil. However, in your case the issue is that Kernel#p and Kernel#puts differ in the values they return.
def hello
# Print string literal, then return
# the printed object.
p "Hey!"
end
# Print the return value of main#hello.
p hello
As a result, the string gets printed once inside the method, and then the method's return value is passed to Kernel#p and printed again. This is by design.
Use Kernel#puts to Avoid Duplicated Output
def hello
# Print string; return nil.
puts "Hey!"
end
# Calls main#hello, but prints nil (blank line).
puts hello
This will result in the string literal being printed inside the method, and then a blank line printed since the return value from the method is nil.
Hey!
=> nil
The Right Way
If you want to avoid the blank line, avoid sending to standard output more than once. For example:
def hello
'Hey!'
end
p hello
If the p method returns the string it's given, then hello would return that as well, which means that the secondary p call would repeat it.
This is probably why puts returns nil by default.

Use of yield and return in Ruby

Can anyone help me to figure out the the use of yield and return in Ruby. I'm a Ruby beginner, so simple examples are highly appreciated.
Thank you in advance!
The return statement works the same way that it works on other similar programming languages, it just returns from the method it is used on.
You can skip the call to return, since all methods in ruby always return the last statement. So you might find method like this:
def method
"hey there"
end
That's actually the same as doing something like:
def method
return "hey there"
end
The yield on the other hand, excecutes the block given as a parameter to the method. So you can have a method like this:
def method
puts "do somthing..."
yield
end
And then use it like this:
method do
puts "doing something"
end
The result of that, would be printing on screen the following 2 lines:
"do somthing..."
"doing something"
Hope that clears it up a bit. For more info on blocks, you can check out this link.
yield is used to call the block associated with the method. You do this by placing the block (basically just code in curly braces) after the method and its parameters, like so:
[1, 2, 3].each {|elem| puts elem}
return exits from the current method, and uses its "argument" as the return value, like so:
def hello
return :hello if some_test
puts "If it some_test returns false, then this message will be printed."
end
But note that you don't have to use the return keyword in any methods; Ruby will return the last statement evaluated if it encounters no returns. Thus these two are equivelent:
def explicit_return
# ...
return true
end
def implicit_return
# ...
true
end
Here's an example for yield:
# A simple iterator that operates on an array
def each_in(ary)
i = 0
until i >= ary.size
# Calls the block associated with this method and sends the arguments as block parameters.
# Automatically raises LocalJumpError if there is no block, so to make it safe, you can use block_given?
yield(ary[i])
i += 1
end
end
# Reverses an array
result = [] # This block is "tied" to the method
# | | |
# v v v
each_in([:duck, :duck, :duck, :GOOSE]) {|elem| result.insert(0, elem)}
result # => [:GOOSE, :duck, :duck, :duck]
And an example for return, which I will use to implement a method to see if a number is happy:
class Numeric
# Not the real meat of the program
def sum_of_squares
(to_s.split("").collect {|s| s.to_i ** 2}).inject(0) {|sum, i| sum + i}
end
def happy?(cache=[])
# If the number reaches 1, then it is happy.
return true if self == 1
# Can't be happy because we're starting to loop
return false if cache.include?(self)
# Ask the next number if it's happy, with self added to the list of seen numbers
# You don't actually need the return (it works without it); I just add it for symmetry
return sum_of_squares.happy?(cache << self)
end
end
24.happy? # => false
19.happy? # => true
2.happy? # => false
1.happy? # => true
# ... and so on ...
Hope this helps! :)
def cool
return yield
end
p cool {"yes!"}
The yield keyword instructs Ruby to execute the code in the block. In this example, the block returns the string "yes!". An explicit return statement was used in the cool() method, but this could have been implicit as well.

Why do this Ruby object have both to_s and inspect methods that appear to do the same thing?

Why do this Ruby object both a to_s and inspect methods that appear to do the same thing?
The p method calls inspect and puts/print calls to_s for representing the object.
If I run
class Graph
def initialize
#nodeArray = Array.new
#wireArray = Array.new
end
def to_s # called with print / puts
"Graph : #{#nodeArray.size}"
end
def inspect # called with p
"G"
end
end
if __FILE__ == $0
gr = Graph.new
p gr
print gr
puts gr
end
I get
G
Graph : 0
Graph : 0
Then, why does Ruby have two functions do the same thing? What is the difference between to_s and inspect?
And what's the difference between puts, print, and p?
If I comment out the to_s or inspect function, I get as follows.
#<Graph:0x100124b88>
#<Graph:0x100124b88>
inspect is used more for debugging and to_s for end-user or display purposes.
For example, [1,2,3].to_s and [1,2,3].inspect produce different output.
inspect is a method that, by default, tells you the class name, the instance's object_id, and lists off the instance's instance variables.
print and puts are used, as you already know, to put the value of the object's to_s method to STDOUT. As indicated by Ruby's documentation, Object#to_s returns a string representing the object -- used for end-user readability.
print and puts are identical to each other except for puts automatically appends a newline, while print does not.
To compare with Python, to_s is like __str__ and inspect is like __repr__. to_s gives you a string, whereas inspect gives you the string representation of the object. You can use the latter to construct an object if you wish.
Further, there is a to_str method on certain objects, which you would call when you need a String-like object, and not just a string representation. (Try in IRB: [1,2,3].to_str and it will fail, yet [1,2,3].to_s will not.) I feel I should mention this because I've been bitten by it before :)
For anyone arriving here after starting out with Ruby Koans, a simple example of where to_s and inspect differ in output is this:
nil.to_s # will yield an empty string, ie ""
nil.inspect # will yield the string "nil"
puts generally prints the result of applying to_s on an object, while p prints the result of inspecting the object.
There is a subtle difference between inspect and to_s:
inspect, when applied on an object, returns the object hex code
along with the instance variable
to_s, when applied on an object,returns only the object hex code
class Item
def initialize(abc)
#abc=abc
end
end
x= Item.new(22)
puts x #prints object x hex code
puts x.inspect #prints object x hex code WITH INSTANCE VARIABLE #abc
puts x.to_s #prints object x hex code
p x #prints object x hex code WITH INSTANCE VARIABLE #abc
p x.inspect #prints object x hex code WITH INSTANCE VARIABLE #abc
p x.to_s #prints object x hex code
Answer from Chris Pine's Learn To Program book
"The inspect method is a lot like to_s, except that the string it returns tries to show you the ruby code for building the object you passed it."
Thus the inspect method will return an array for example like this...
[25, 16, 9, 4, 1, 0]
Where as puts / to_s will return
25
16
9
4
1
0
2.0.0p195 :075 > puts (1..5).to_a # Put an array as a string.
1
2
3
4
5
=> nil
2.0.0p195 :076 > puts (1..5).to_a.inspect # Put a literal array.
[1, 2, 3, 4, 5]
=> nil
2.0.0p195 :077 > puts :name, :name.inspect
name
:name
=> nil
2.0.0p195 :078 > puts "It worked!", "It worked!".inspect
It worked!
"It worked!"
=> nil
2.0.0p195 :079 > p :name # Same as 'puts :name.inspect'
:name
=> :name
From the Rails Tutorial
Refer following link for more information and examples explaining difference between "to_s" and "inspect" as well as difference between "puts" and "p".
https://rubymonk.com/learning/books/4-ruby-primer-ascent/chapters/45-more-classes/lessons/108-displaying-objects

Resources