Dragon
Dragon

Reputation: 31

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.

Upvotes: 0

Views: 3477

Answers (4)

sbs
sbs

Reputation: 4152

puts "Loud Bark"   # => returns nil
return "Loud Bark" # => returns "Loud Bark"

Upvotes: 0

Semjon
Semjon

Reputation: 1023

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 

Upvotes: 1

sawa
sawa

Reputation: 168081

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.

  1. All arguments passed to a method are evaluated prior to the method call.
  2. 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.

Upvotes: 1

Ray
Ray

Reputation: 66

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.

  1. It's calling the puts method (displaying Loud Bark to the terminal screen)
  2. 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

  1. Calls the name method
  2. 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)
  3. The value is then saved to a temporary variable

At this point, our temporary variable is Max goes.

  1. Calls the bark method
  2. The line puts "Loud Bark" gets executed since we're calling it in the bark method.
  3. Terminal(console) displays "Loud Bark"
  4. 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)
  5. nil is then converted to the closest string representation (which is "")
  6. It is then saved to a temporary variable

The temporary variable is now Max goes

  1. Now, the temporary variable is passed into the puts method, and the terminal(console) displays "Max goes "

  2. 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!

Upvotes: 5

Related Questions