CodeCrack
CodeCrack

Reputation: 5363

ruby's =~ operator return values?

def starts_with_consonant?(s)
  if /^(a|e|i|o|u).*/i =~ s
    true
  else
    false
  end
end

# prints out true
puts starts_with_consonant?('aa') 

# prints out false
puts starts_with_consonant?('da')

If I change the code just to

def starts_with_consonant?(s)
  /^(a|e|i|o|u).*/i =~ s
end

Is that same functionality because

puts starts_with_consonant?('aa').inspect

prints out 0 (Shouldn't it be 1?)

puts starts_with_consonant?('da').inspect

prints out nil

# both print out 0
 puts starts_with_consonant?('aa').to_i
 puts starts_with_consonant?('da').to_i

What gives?

Upvotes: 1

Views: 445

Answers (5)

Michael Durrant
Michael Durrant

Reputation: 96484

Your getting back truthy. You can't print it but you can use it, e.g.

2.0.0-p247 :007 > if "aaaabcd" =~ /a/ then puts "true" end
true
 => nil 

2.0.0-p247 :008 > if "aaaabcd" =~ /aaa/ then puts "true" end
true
 => nil 

2.0.0-p247 :009 > if "aaaabcd" =~ /z/ then puts "true" end
 => nil 

Similarly you can set a variable based on the evaluation, i.e.

2.0.0-p247 :013 >   if "aaaabcd" =~ /a/ then b=1 end
 => 1 

2.0.0-p247 :014 > if "aaaabcd" =~ /aaa/ then b=1 end
 => 1 

2.0.0-p247 :015 > if "aaaabcd" =~ /zzz/ then b=1 end
 => nil 

Upvotes: 0

user513951
user513951

Reputation: 13650

Your first method, with the if/else statement, is treating the result of the =~ check as "truthy value or not?". If the match is found in the string, it returns the index (in your case, 0) or if it is not found, it returns nil.

0 is a truthy value; nil is not.

Therefore, even though it's returning the same result in each of your methods containing the /.../ =~ s expression, you get different return values out of the methods, depending on what you do with that result.

In the if/else statement, you get true when it's the truthy value of 0, and false when it's the non-truthy value of nil.

In the bare return statement, you get the plain return values of 0 and nil.

Upvotes: 0

August
August

Reputation: 12558

The =~ operator returns the first match index if the String and Regexp match, otherwise nil is returned:

'foo' =~ /bar/ # => nil

'foo bar' =~ /bar/ # => 4

Upvotes: 1

Amadan
Amadan

Reputation: 198334

puts starts_with_consonant?('aa').inspect

prints out 0 (Shouldn't it be 1?)

No, it should be 0. Strings are zero-indexed, the pattern has been found on the zeroth position. 0 is a truthy value, triggering the if clause if evaluated there. 'da' =~ /a/ would return 1, since a is the 1st character in the string (d being 0th).

puts starts_with_consonant?('da').inspect

prints out nil

There is no position that matches the pattern, so the return value is nil, a falsy value, which triggers the else clause if evaluated as an if condition.

# both print out 0
puts starts_with_consonant?('aa').to_i
puts starts_with_consonant?('da').to_i

Because both 0.to_i and nil.to_i result in 0.

Upvotes: 0

Anthony
Anthony

Reputation: 15967

well the #=~ method actually returns the index where the first match occurs.

You can't do nil.to_i because that produces zero.

[6] pry(main)> nil.to_i
=> 0

Upvotes: 0

Related Questions