9

So, I'm running into this issue wherein I want to have three conditions be checked before the routine continues, but it keeps throwing up syntax errors saying it didn't expect the multiple conditions. Now, I know I've seen other people use lines such as:

if x > 100 && x % 2 == 1
    #Do something
end

But, for whatever reason, this line:

if (letters.eql? letters.upcase && dash.eql? '-' && numbers.to_i.to_s.eql? numbers)

is throwing up tons of errors. Is it something to do with '.eql?' or is it something extraneous about Ruby that I haven't encountered yet?

Here's the rest of the code for reference:

print "Enter license plate: ";
input = gets.strip;
if input.length == 8
    letters = input[0,2];
    dash = input[3];
    numbers = input[4,7];
    if (letters.eql? letters.upcase && dash.eql? '-' && numbers.to_i.to_s.eql? numbers)
        puts "#{input} is a valid license plate."
    else
        print "All valid license plates are three (3) uppercase letters, followed by a dash (-), followed by four (4) digits";
    end
else
    print "All valid license plates are 8 characters long.";
end

Also, these are the errors:

LicensePlate.rb:7: syntax error, unexpected tSTRING_BEG, expecting ')'
...? letters.upcase && dash.eql? '-' && numbers.to_i.to_s.eql? ...
...                               ^
LicensePlate.rb:7: syntax error, unexpected tIDENTIFIER, expecting ')'
... numbers.to_i.to_s.eql? numbers)
...
Jeffrey Green
  • 153
  • 1
  • 2
  • 9
  • what errors do you get? – ivan Dec 14 '15 at 21:06
  • 1
    use parentheses `letters.eql?(letters.upcase) && dash.eql?('-') && numbers.to_i.to_s.eql?(numbers)` right now it is trying to see if `letters == (letters.upcase && dash == ('-' && numbers.to_i.to_s.eql? numbers))` – engineersmnky Dec 14 '15 at 21:06
  • @lurker so how does precedence effect the necessity for parenthesis' when calling methods in Ruby? – Jeffrey Green Dec 14 '15 at 21:13
  • 1
    @JeffreyGreen sorry "precedence" may not be the right term to use in this case, but Ruby provides the "convenience" of leaving off parentheses when making a method call, like `foo a, b`. This works fine until you get a lot of different things going on the line, like in your logical expression. In that case it becomes ambiguous and Ruby isn't sure that `letters.eql?` is a method call any more. Or it might consider it a method with no arguments. The parentheses ensure that it is interpreted properly. Your error message (which you haven't indicated) will give clues as to what Ruby thinks. – lurker Dec 14 '15 at 21:14
  • Thanks @lurker! That's a much more thorough explanation of what's happening and it's very much appreciated. – Jeffrey Green Dec 14 '15 at 21:19
  • You could also use regex like this - `if input =~ /[A-Z]{3}-\d{4}/`. Also the second param in `input[0,2]` is supposed to be length (not the end-index) - so you should be using `input[0,3]` and `input[4,4]` – Wand Maker Dec 15 '15 at 04:23

4 Answers4

10

This should do it:

if letters.eql?(letters.upcase) && dash.eql?('-') && numbers.to_i.to_s.eql?(numbers)

You can still wrap the entire conditional in parenthesis if you would like, but with Ruby (unlike JavaScript), you don't need to.

Ryan Rebo
  • 1,278
  • 2
  • 13
  • 27
  • Can you explain why this is the case? This did solve my problem, but an explanation would be helpful for those who find this question in the future. – Jeffrey Green Dec 14 '15 at 21:20
  • @JeffreyGreen It's really just a matter of Ruby being a language that tends toward flexible syntax, in my opinion. If you find it more readable to wrap the whole thing in parenthesis, go for it, it will work! If you want to take advantage of Ruby's flexibility, you leave it out. – Ryan Rebo Dec 14 '15 at 21:25
6

Think you're just missing some parens - try this:

if (letters.eql?(letters.upcase) && dash.eql?('-') && numbers.to_i.to_s.eql?(numbers))

Rob Mulholand
  • 899
  • 7
  • 7
  • Oh, okay, so what's happening is that .eql? is calling a method, which when calling multiple methods on the same line, you DO have to include parenthesis'? Is there a reason why this is the case? – Jeffrey Green Dec 14 '15 at 21:10
4

This also works:

letters.eql? letters.upcase and dash.eql? '-' and numbers.to_i.to_s.eql? numbers

I believe this is due to operator precedence since this also works:

(letters.eql? letters.upcase) && (dash.eql? '-') && (numbers.to_i.to_s.eql? numbers)

Ruby seem to try and evaluate your condition prematurely.

EDIT: Just saw that Lurker was mentioning precedence previously.

Ohad Dahan
  • 371
  • 3
  • 14
1

In addition to the other answers - consider using a regular expression to check the format:

print "Enter license plate: "
input = gets.chomp
if input.length != 8
  puts "All valid license plates are 8 characters long."
elsif input !~ /^[A-Z]{3}-\d{4}$/
  print "All valid license plates are three (3) uppercase letters, followed by a dash (-), followed by four (4) digits"
else
  puts "#{input} is a valid license plate."
end
Stefan
  • 109,145
  • 14
  • 143
  • 218