2

The following conditional syntax displays the string 'is true' in irb without using puts

irb(main):001:0> if true
irb(main):002:1>   'is true'
irb(main):003:1> else
irb(main):004:1*   'is false'
irb(main):005:1> end
=> "is true"

...yet when I invoke the same syntax in a script and run it from the command line, it gets ignored. Why?

# Odd behaviour:
puts "Why do only two of the three conditionals print?"

# This doesn't put anything to screen:
if true
  'is true_1'
else
  'is false'
end

puts "Seriously, why? Or better yet: how?"

# But this does:
if true
  puts 'is true_2'
else
  puts 'is false'
end

# And this works without "puts":
def truthiness
  if 1.send(:==, 1)
    'is true_3'
  else
    'is false'
  end
end

puts truthiness
puts "Weird."

When I run this as a script, it displays:

"Why do only two of the three conditionals print?
Seriously, why? Or better yet: how?
is true_2
is true_3
Weird."

FWIW, I am following along with Sandi Metz's talk "Nothing is Something" https://youtu.be/zc9OvLzS9mU ...and listening to this: https://youtu.be/AULOC--qUOI Apologies as I am new to Ruby and trying to wrap my head around how it does what it does.
EDIT: Useful resources:
http://ruby-doc.org/core-2.3.1/Kernel.html#method-i-puts
https://softwareengineering.stackexchange.com/questions/150824/is-the-puts-function-of-ruby-a-method-of-an-object

Community
  • 1
  • 1
MmmHmm
  • 3,435
  • 2
  • 27
  • 49
  • 1
    irb prints out the return value of each command you type. Kind of like an interactive debugger. When a script is run, it does not output anything, unless told to with `puts` or similar. – David Hempy Apr 09 '18 at 14:58

1 Answers1

4

The IRB output here is showing the return value of the operation, which is not necessarily what is printed to STDOUT (i.e. the terminal) during execution.

Your script is just throwing the return value away, you would have to do this:

val = if true
        'is true_1'
      else
        'is false'
      end

puts val
Ginty
  • 3,483
  • 20
  • 24
  • Interesting... will have to get familiar with begin, looks very useful. Of note, when I use the explicit `puts` in the irb conditional, I get the 'is true' printed along with another line of `=> nil` – MmmHmm Sep 07 '16 at 06:50
  • 1
    Ah yes, sorry about that, you are seeing the return value of the puts operation which is nil. I've edited my answer appropriately. – Ginty Sep 07 '16 at 06:53
  • 1
    That's because [`Kernel#puts` returns `nil`, as stated in the documentation](http://ruby-doc.org/core/Kernel.html#method-i-puts). – Jörg W Mittag Sep 07 '16 at 06:54
  • 1
    @Ginty: you don't need `begin` here. You can just do `val = if true ...` – Sergio Tulentsev Sep 07 '16 at 06:57
  • 1
    What's the purpose of the `begin` block? You don't have any exceptions, you don't have multiple expressions, what do you need it for? – Jörg W Mittag Sep 07 '16 at 06:57
  • 1
    @Mr.Kennedy: "I get the 'is true' printed along with another line of => nil". Of course. One is return value, the other - side-effect. – Sergio Tulentsev Sep 07 '16 at 06:58
  • @JörgWMittag - excellent resource, I have much to learn about the Kernel and Ruby innards. Thank you. – MmmHmm Sep 07 '16 at 07:02
  • @SergioTulentsev so in the instance of "true_3", Ruby is printing the string without an explicit call to the `puts` method in the function... Hmmm... I see that "truthiness.class" identifies a String... so essentially truthiness returns-- no, "evaluates" to a String value and then the call to "puts truthiness"... Okay... I'm starting to understand... :P – MmmHmm Sep 07 '16 at 07:23
  • @Ginty is irb showing the "return" value, or would it be more correct to say that irb is displaying the conditionals evaluation? – MmmHmm Sep 07 '16 at 07:25
  • 3
    @Mr.Kennedy: IRb is a REPL - a Read Eval Print Loop. It Reads what you type into it, Evaluates the code, Prints out its value, then Loops back to the beginning (i.e. Reads the next expression). So, yes, it is printing the result of evaluating the expression. This is commonly shortened to saying "return value", although strictly speaking there is no method call and thus no `return`. (More precisely: IRb is printing the result of calling the [`inspect`](http://ruby-doc.org/core/Object.html#method-i-inspect) method on the object that is the value of evaluating the expression.) – Jörg W Mittag Sep 07 '16 at 07:37
  • @JörgWMittag your explanation helps enormously. Much obliged! – MmmHmm Sep 07 '16 at 07:40