About Ruby error 'kEnd'? - ruby

I'm having a lot of trouble with Ruby after coming back to it from a long break.
I'm getting a lot of 'unexpected kEND' errors, and I've tracked it down to lines below. I'm not having trouble with a particular piece of code, but rather, the concept of 'unexpected kEND' .
if (condition)
do-one-line-thing()
and
# inside of a loop...
if ( condition-evaluation-that-might-cause-error-during-run-time )
do-something()
end
and
myarray.each { |element|
do-soemthing-that-might-cause-error-during-run-time-for-some-but-not-all-values()
}
Question :
What other things can cause these kEND errors ? It seems like kEND is being used as a general "Badness on line ##" error? What can you tell me about kEND errors in general?

an unexpected kEND is where the end keyword was found somewhere it shouldn't be.
Generally you've closed too many code blocks, or you've got some other syntax problem.
If you paste a (complete) file which has this problem we can point out the error...

There is a syntax error in the first piece of code
if (condition)
do-one-line-thing()
You always have to explicitly close the if clause with end. You cannot omit it, like you do in many other languages, even if the block consists of a single line.

Related

Validate Ruby Syntax using Ruby

I need to validate that a given string is valid Ruby syntax, programmatically, using Ruby. I imagine one way I can do this is by running the code in an EVAL statement, and detecting syntax errors that way.
What's a more proper, safer way I can accomplish this?
Let the code string be code. The standard way is to do something like this:
begin
RubyVM::InstructionSequence.compile(code)
nil
rescue Exception => e
... # Put code here to return `e` itself, print its message, or whatever you like
end
If an error is raised and is rescued, that error will display the syntax error. If not (and nil is returned), then code is syntactically valid Ruby code (which does not guarantee that it is free of other types of errors).
The comments saying it is dangerous to do, etc, does not seem to make sense.
I'd consider checking this in the browser with Opal - https://github.com/opal/opal

Encountering: syntax error, unexpected tIDENTIFIER, expecting keyword_end

I'm creating a directed_graph class in Ruby to practice using RSpec. I keep getting the above error (at line 13, which is the line below with "eql(0)" on it).
I don't really understand the error, especially since this RSpec code looks very similar to other RSpec code I've written for other projects that works.
require "directed_graph"
include directed_graph
describe directed_graph do
describe ".vertices" do
context "given an empty graph" do
it "returns an empty hash" do
g = directed_graph.new()
expect(g.vertices().length()).to() eql(0)
end
end
end
end
EDIT: I believe the problem was (1) directed_graph was a class, and classes must start with uppercase letters (so I renamed is DirectedGraph), and (2) you're not supposed to write "include" for classes.
I fixed those two, and my code seems to be runnign fine for now. I'm going to leave this up here in case I missed something big.
I believe the code should look like this:
require "directed_graph"
include DirectedGraph
describe DirectedGraph do
describe ".vertices" do
context "given an empty graph" do
it "returns an empty hash" do
expect(directed_graph.new.vertices.length).to eql(0)
end
end
end
end
Let me explain why. First include usually includes Classes/Modules. Classes and modules in ruby are denoted with Capital Letters for each part of their name (also know as UpperCamelCase). When you describe a class in in rspec, you should also use UpperCamelCase. I also cleaned up the code a little bit to make it easier to read. You don't always need the () to denote a function. It is implied. But sometimes you do need it, for example with the expect function.

Is it possible to use `retry` keyword inline with `if`?

I have to surround everything with begin-rescue-end block. I've written code that looks like:
begin
bet = Dialogs.enter_your_bet
approx.calculate_average_profit(bet)
approx.print_profits_table
retry if Dialogs.play_again?
rescue;retry
end
The line retry if Dialogs.play_again? caused the following error:
./main:14: Invalid retry
./main: compile error (SyntaxError)
Is it possible to make this kind of inline retry to work with if clause without regular if-end multiline approach?
retry works in rescue blocks (or in iterators). And it works with if. Try this:
begin
bet = Dialogs.enter_your_bet
approx.calculate_average_profit(bet)
approx.print_profits_table
rescue
retry if Dialogs.play_again?
end
Ok, thank you all for answers! I understood what was a problem, but your workarounds wasn't what I need. Actually, rescue part was for restarting input prompt in case of illegal input from a user, while my 'retry' inside begin was to restart block from another user input (y/n question).
So after some investigation, this code would work flawlessly:
begin
loop do
bet = Dialogs.enter_your_bet(gapes[0],gapes[1])
approx.calculate_average_profit(bet)
approx.print_profits_table
break if !Dialogs.play_again?
end
rescue;retry
end
And again, thanks for been so awesomely active community. Take care!
redo is used for control flow.
Quoting the docs: "In Ruby 1.8 you could also use retry where you used redo. This is no longer true, now you will receive a SyntaxError when you use retry outside of a rescue block. See Exceptions for proper usage of retry."

Can I put an if/unless clause on the next line in Ruby?

In Perl, I often find myself using the following pattern:
croak "incompatible object given: $object"
unless $object->isa('ExampleObject') and $object->can('foo');
I tried to translate this into Ruby like this:
raise ArgumentError, "incompatible object given: #{object.inspect}"
unless object.is_a?(ExampleObject) and object.respond_to?(:foo)
But that does not work because Ruby interprets unless as the start of a new statement. As far as I understand, I can put a backslash at the end of the first line, but that looks ugly and feels wrong. I could also use a regular unless condition raise error end structure, but I like the style of the original form more. Is there a nice (and idiomatic) way to write this as a single statement in Ruby?
Can I put an if/unless clause on the next line in Ruby?
You can't. From page 107 (PDF page 127) of the final draft of ISO Ruby which usually isn't relevant, but basic things like this are and it also spares us from having to read parse.y:
unless-modifier-statement ::
statement [no line-terminator here] unless expression
This is pretty clear. It just doesn't get more similar to your Perl example than:
raise ArgumentError, "incompatible object given: #{object.inspect}" unless
object.is_a?(ExampleObject) and object.respond_to?(:foo)`
or:
raise ArgumentError, "incompatible object given: #{object.inspect}" \
unless object.is_a?(ExampleObject) and object.respond_to?(:foo)
Just as you feel wrong to put a backslash at the end to force a single line statement, it is wrong to use a single line statement when it extends beyond a single line.
This is not really a solution, I was sloppy when reading the question. The OP wants a solution without backslash.
You should be able to do this:
raise ArgumentError, "incompatible object given: #{object.inspect}" \
unless object.is_a?(ExampleObject) and object.respond_to?(:foo)
The \ characters tells ruby to keep reading as if there was no line break.
As far as I know there is no other way than a \, since otherwise, as you already said, Ruby thinks it's a new statement.
Keep in mind that style guides and conventions differ from language to language. In Ruby I'd not expect an if/unless statement in a line coming after it's code. In fact I even dislike putting if/unless at the end of a line, since it reverses the reading direction from If this, then that to that, if this (then what? Ah, I need to read back again), especially when the condition is more complex than raise 'foo' if bar.empty?.
In Perl and other languages though this might be different, since you have other conventions, style guides and this ;-thingy ;)

Ruby method list: "unexpected kDEF, expecting $end"

I feel pretty dumb having to ask this, but it's had me stumped way too long. Attempting to run the following, I get
finance.rb:1: syntax error, unexpected kDEF, expecting $end
def get_sign(input)
return "+" if input.include? "+"
return "-" if input.include? "-"
end
def get_account_name(input)
if input.split[0] == "new"
return input.split.reject{|x| x == "new" or x == "account"}[0]
else
return input.split[0]
end
end
If I wrap them in a class, it just expects <, \n, or ; instead of $end.
Ruby 1.8.7 and 1.9 (via Macruby) give the same error. Removing the second method seems to get it working. Someone, please enlighten me; this seems like a really fundamental misunderstanding of something on my part.
I don't get this error if I copy/paste your contents from this question into a new file. If you do so (copy/paste from this web page into a new file and save that) do you still get the error? If not, perhaps you have some garbage whitespace in your file?
Added as answer because another user may find this question with a similar problem and not read through all the comments to find the solution.

Resources