vaibhavatul47
vaibhavatul47

Reputation: 2885

Ruby: how to combine puts and return inside if condition?

How can I print a message and then return from a function in ruby?

2.3.4 :038 > def foo(num)
2.3.4 :039?>   print "Your number is: #{num}" && return if num > 10
2.3.4 :040?>   print "Number too small"
2.3.4 :041?>   end
 => :foo
2.3.4 :042 > foo(47)
 => nil
2.3.4 :043 > foo(7)
Number too small => nil
2.3.4 :044 >

When I called foo with 47 why didn't I got Your number is: 47 in output?

PS: This function can be written in other simpler ways also, I just wanted to express my doubt via this function.

Upvotes: 4

Views: 3140

Answers (6)

EliadL
EliadL

Reputation: 7068

Since print (and puts) returns nil, this works just as well:

def foo(num)
  return print "Your number is: #{num}" if num > 10
  print "Number too small"
end

And to show clearer intention, place the guard clause first:

def foo(num)
  return print "Number too small" if num <= 10
  print "Your number is: #{num}"
end

Examples:

> foo 47
Your number is: 47=> nil
> foo 7
Number too small=> nil

Upvotes: 3

spickermann
spickermann

Reputation: 106792

Because Ruby reads this line

print "Your number is: #{num}" && return if num > 10

like this

print("Your number is: #{num}" && return) if num > 10

That leads the method to return before it had the chance to print anything.

Adding a pair of parenthesis helps Ruby to resolve the desired order:

print("Your number is: #{num}") || return if num > 10

Upvotes: 6

Stefan
Stefan

Reputation: 114138

You have a precedence issue which can be fixed using parentheses. But since you are trying to express a control flow, you should use the control flow operators and and or instead of the boolean operators && and ||.

The idiom works like this: (just examples, it's not limited to return and fail)

do_something and return "it worked"

or:

do_something or fail "it didn't work"

It allows you to evaluate a second expression depending on whether the first expression succeeded or not. do_something is supposed to return a truthy value in case of success and a falsey value in case of failure.

print however always returns nil, so it doesn't work as expected in this regard. You would have to reverse the logic:

print "Your number is: #{num}" or return

But this doesn't read naturally any more, does it? Beside, return is always invoked, because print will never return a truthy value. You actually want:

print "Your number is: #{num}"
return

I would therefore simply write:

def foo(num)
  if num > 10
    puts "Your number is: #{num}"
  else
    puts "Number too small"
  end
end

Upvotes: 4

meshin
meshin

Reputation: 478

One more way to do one line if statements is with ;

def foo(num)
  if num < 10; print "Your number is: #{num}" && return; end
  print "Number too small"
end

Upvotes: 1

Aleksei Matiushkin
Aleksei Matiushkin

Reputation: 121000

Just out of curiosity:

def foo(num)
  print case num
        when -Float::INFINITY...10 then "Number too small"
        else "Your number is: #{num}"
        end
end

Upvotes: 1

Ronan Lopes
Ronan Lopes

Reputation: 3398

def foo(num)
   puts(num > 10 ? "Your number is: #{num}" : "Number too small")
end

I think this is the cleaner way to do that, with an If ternary. Hope this helps

Upvotes: 3

Related Questions