Why is "true || File.exist? 'touch'" invalid syntax? - ruby

The following is invalid:
true || File.exist? 'touch'
SyntaxError: unexpected tSTRING_BEG, expecting end-of-input
true || File.exist? 'touch'
^
However, if you remove the true ||, or use brackets around 'touch', it's valid:
File.exist? 'touch'
=> false
true || File.exist?('touch')
=> true
Why is the combination of the true || and not using brackets invalid syntax?
Doing a search for SyntaxError: unexpected tSYMBEG only got https://github.com/bbatsov/rubocop/issues/1232 , and doing a search for SyntaxError: unexpected tSTRING_BEG seemed to mainly get people who'd made some sort of typo such as RoR: syntax error, unexpected tSTRING_BEG, expecting ')' and Ruby syntax error, unexpected tSTRING_BEG, expecting ':' (SyntaxError)

This will work
true or File.exist? 'touch'
The reason is does is because || has higher precedence than or, and with || your expression simplifies to (true || File.exist?) 'touch'.
I'm not recommending you use or, but consider always using parenthesis - most Ruby guidelines (Vanilla Ruby and Rails) recommend using them at all times.
Community driven ruby style guide:
Omit parentheses around parameters for methods that are part of an internal DSL (e.g. Rake, Rails, RSpec), methods that have "keyword" status in Ruby (e.g. attr_reader, puts) and attribute access methods. Use parentheses around the arguments of all other method invocations.

Related

What's the difference between keyword_end and end-of-input in ruby?

Sometimes, I ran into an error like this in ruby:
syntax error, unexpected keyword_end, expecting end-of-input
So, I want to know the difference between keyword_end and end-of-input
Keyword 'end' is the end statement in Ruby that comes at the end of methods, classes, etc. end-of-input is the actual end of your code file. The message you got means you have an extra 'end' statement somewhere.
keyword_end implies that you had a block of code with a missing end.
def fun(f)
puts "Oops!"
End-of-input implies that you have already closed up blocks of code with one too many end keywords.
def fun(f)
puts "Okay..."
end
end

Ruby - end pattern with unmatched parenthesis: /

I'm getting different error based on space between after divide(/) operator. Lets consider following example.
$ ruby -e "a /100"
-e:1: unterminated string meets end of file
-e:1: syntax error, unexpected tSTRING_END, expecting tSTRING_CONTENT or tREGEXP_END or tSTRING_DBEG or tSTRING_DVAR
$ ruby -e "a / 100"
-e:1: undefined local variable or method `a' for main:Object (NameError)
The second example gives proper error message while the first one gives weird error. I did some research, but couldn't find out the reasons behind it. Is there anyway to fix this to give proper error messge?
If I try this with Ruby 2.3.1, I get this message: -e:1: unterminated regexp meets end of file Which seems valid since "/" is normally a regex marker...
And in the second line of your error message it says it is expecting a tREGEXP_END.
So, I think, everything is fine.
I tried this in the terminal and got the same regexp error:
$ ruby -e "a /100"
-e:1: unterminated regexp meets end of file
It seems like the /100 was interpreted as a regexp. The simple solution is to follow the correct ruby syntax (i.e. your second example: $ ruby -e "a / 100" ). Normally, it is recommended to add spaces around ruby operators, as suggest by the ruby style guide.

Multiline if else ruby

I know this questions has been touched on elsewhere, but I'm slightly confused about the proper syntax for multi-line (block?) if else statements in ruby.
As an example:
if condition then
do something
do somethingelse
do yetanotherthing
done
else
do acompletelyunrelatedthing
done
I understand that the then statement is required if multiple lines are used, but is the done before the else necessary? This seems like it would break out of the if...else context. When I do include this done I get:
syntax error, unexpected '\n', expecting tCOLON2 or '[' or '.'
When I don't include it I get:
syntax error, unexpected keyword_else, expecting keyword_end
Um... there is no done keyword in Ruby. Here is the correct syntax:
if condition
# do stuff
else
# do other stuff
end
The then keyword is not needed either.
The then keyword is only used if you need to put the whole thing on one line (to separate the condition from the action to take if true):
if condition then do_something else do_something_different end
If you don't want it all one line (usually you don't), the syntax is as in Doorknob's answer.

Weird syntax error when comparing x with x.method

Why this works fine:
t="
"+$<.read;puts t.reverse==t ?"YES":"NO"
but this:
t="
"+$<.read;puts t==t.reverse ?"YES":"NO"
says:
A.rb:2: syntax error, unexpected tCHAR, expecting $end
"+$<.read;puts t==t.reverse ?"YES":"NO"
^
I use ruby 1.9.2p290 (2011-07-09) [i386-mingw32].
Sample STDIN string is XX.\n...\n.XX\n.
Looks like Ruby is parsing the latter as a potential call to #reverse?. That ambiguity is removed when switched the other way. Adding parentheses around the conditional should allow it to go both ways.

Is there a quick way to find missing end’s in Ruby?

syntax error, unexpected $end, expecting keyword_end
We’ve all been there! Assuming enough code changed that a quick glance at git diff or the like doesn’t make it obvious, is there an easy way to find that missing end (short of switching to an indentation-based language like Python)?
FWIW, I use Sublime Text 2 as my editor.
If you're using Ruby 1.9, try the -w flag when running your ruby program.
# t.rb
class Example
def meth1
if Time.now.hours > 12
puts "Afternoon"
end
def meth2
# ...
end
end
ruby t.rb
=> t.rb:10: syntax error, unexpected $end, expecting keyword_end
ruby -w t.rb
=> t.rb:5: warning: mismatched indentations at 'end' with 'if' at 3
t.rb:9: warning: mismatched indentations at 'end' with 'def' at 2
t.rb:10: syntax error, unexpected $end, expecting keyword_end
Source:
http://pragdave.blogs.pragprog.com/pragdave/2008/12/ruby-19-can-check-your-indentation.html
Edit (2023): this is now part of Ruby 3.2 and doesn‘t need to be required separately!
————————————
Edit (2022): the gem is now called syntax_suggest and is part of the Ruby standard library!
————————————
Since December 2020, there is also the dead_end gem which helps you detect missing ends.
The easiest way to get started is to install the gem:
gem install dead_end
and run it directly from your console, providing the file name to scan:
dead_end myfile.rb
This will provide you with a more helpful error message:
43 if (col_idx - 1) % 3 == 0
50 if !contains?(doc, node)
❯ 51 doc.add_child(node)
❯ 52 tree.
53 end
54 end
See the documentation for more options.
If you're using rails, you can run the problematic file specifically with the -w flag.
If you still can't find the offending mismatch, then my go-to way of solving this problem is just commenting out chunks of code until I can isolate the problematic area.
On OS X you can use command + / to comment out the highlighted piece of text.

Resources