brooklynsweb
brooklynsweb

Reputation: 817

Why does using the shorthand "if" syntax does not evaluate when searching for a sub-string using "include?"

I attempted to use the shorthand to get a response based on the existance of a sub-string, instead of the expected string response, it evaluated to "false." In my second simpler example the expect string was printed.

#fails

puts "test".include? "s" ? "yep" : "nope" 

#success

puts 1>2 ? "1 is greater than 2" : "1 is not greater than 2"

Upvotes: 1

Views: 44

Answers (2)

Jon Kiparsky
Jon Kiparsky

Reputation: 7743

It looks like ruby is unable to parse this as you're expecting without a little help. It thinks you're doing

puts "test".include?("s" ? "yep" : "nope")

You need to either use the (optional) parens around the argument

puts "test".include?("s") ? "yep" : "nope"

or force the test expression to be interpreted as a whole:

puts ("test".include?"s") ? "yep" : "nope"

Upvotes: 2

Eric Duminil
Eric Duminil

Reputation: 54233

It's a precedence problem.

Solution

You need :

puts "test".include?("s") ? "yep" : "nope"
#=> yep

Why?

Method call without parenthesis is somewhere between defined? and or in the precedence table, so it is lower than the ternary operator. It means that

puts "test".include? "s" ? "yep" : "nope"

is parsed as

puts "test".include?("s" ? "yep" : "nope")

which is

puts "test".include?("yep")

which is

false

Warning

"s" ? "yep" : "nope"

displays a warning :

warning: string literal in condition

because ternary operator expects a boolean, and a String is always truthy.

1 > 2

The reason this works

puts 1>2 ? "1 is greater than 2" : "1 is not greater than 2"

is that the ternary operator has a higher precedence than puts :

puts ( 1>2 ? "1 is greater than 2" : "1 is not greater than 2" )

It is evaluated as :

puts ( "1 is not greater than 2" )

One last tip

When you have precedence problem, using puts without parenthesis might just make the problem worse. You can fire up IRB and see what the result is directly.

Here's an example :

# in a script :
puts [1,2,3].map do |i|
  i * 2
end
#=> #<Enumerator:0x0000000214d708>

With IRB :

[1,2,3].map do |i|
  i * 2
end
# => [2, 4, 6]

Upvotes: 6

Related Questions