NoMethodError: undefined method `+#' for "some sting":String - ruby

My rails app just started receiving this error today. Here is the code context. It is throwing the error on the line that starts with new_host_id
while #host_ids.include?(new_host_id)
i++
new_host_id = duplicate_host_id + i.to_s
end

Ruby does not have a ++ operator.
The idiom in Ruby is i += 1, which is the abbreviated form of i = i + 1.
Initially I thought that the posted code was incorrect and had to be ++i to generate that error. However, as Jörg W Mittag explains in a comment, this is not the case:
[..] Ruby allows whitespace (including line breaks) between an operator and the operand(s), so the entire thing is interpreted as i + (+(new_host_id = duplicate_host_id + i.to_s)) [.. which is] why the NoMethodError refers to String.
Here is a simplified example showing the issue (the posted code refers to the first case):
> x = "hello"
> +x
undefined method `+#' for "hello":String (NoMethodError)
> x+
syntax error, unexpected $end
I used + and not ++ above to simplify the example: Ruby treats ++i and i++ as the productions +(+i) and [roughly] i+(+) ..

It turns out the error was caused by the previous line i++
I changed i++ to i = i + 1 and it's working now.
Here's the working code
while #host_ids.include?(new_host_id)
i = i + 1
new_host_id = duplicate_host_id + i.to_s
end

If you had warnings on, you'd probably have got a warning about that line.
$VERBOSE = true
def foo
i = 2
i++
j = 5
j + i
end
warning: possibly useless use of + in void context

Related

Writing a Ruby class method and getting unexpected token kEND error

I am writing a class, Wrapper, and am giving it a class method self.wrap. I am getting an unexpected end-of-input error. I have been staring at the code forever and can't see where the mistake might be. I think I have all of my end's in place. What am I missing?
require 'pry'
class Wrapper
def self.wrap(input_string, column_number)
position = 0
num_inserted = 0
while (position + column_number < line.length) do
last_space_index = input_string.rindex(" ", position + column_number)
if last_space_index > position - 1
input_string[num_inserted + last_space_index] = "\n"
else
input_string.insert(num_inserted + position + column_number, "\n")
position += column_number
num_inserted ++
end
end
end
end
There is no ++ operator in Ruby.
Instead, you can write:
num_inserted = num_inserted + 1
Or for short:
num_inserted += 1
The error message you're seeing is admittedly quite confusing/misleading.
However, if you use an IDE with language-aware syntax highlighting (something I would highly recommend all programmers, in all languages, set up as a high priority for development) then this should at least highlight exactly which line of code is causing the problem.
For example, entering your code in my local setup reveals the error:
`+' after local variable or literal is interpreted as binary operator
even though it seems like unary operator

Unclear syntax error in Ruby : "syntax error, unexpected end" when using an invalid operator

I am trying to make sense of why Ruby reported the syntax error that it did , and why it could not be more clear. The following code snippet is giving me a "syntax error, unexpected end"
# #param {NestedInteger[]} nested_list
# #return {Integer}
def depth_sum(nested_list)
queue = Queue.new
nested_list.each { |element| queue.enq element }
result = 0
level = 1
until queue.empty?
size = queue.size
size.times do
element = queue.pop
if element.is_integer
result += level * element.get_Integer
else
element.each { |elem| queue.enq(elem) }
end
end
level++
end
end
I then figured out that Ruby does not have the ++ operator , so i replaced level++ with level+=1 and the code worked. But why was Ruby's syntax error message so cryptic about an unexpected end when in fact my error was not due to the "end" but because I was using a ++ operator which is not used in Ruby.
In Ruby, it is allowed to have whitespace between an operator and its operand(s). This includes newlines, and it includes unary prefix operators. So, the following is perfectly valid Ruby:
+
foo
It is the same as
+ foo
which is the same as
+foo
which is the same as
foo.+#()
The following is also perfectly valid Ruby:
foo++
bar
It is the same as
foo ++ bar
which is the same as
foo + + bar
which is the same as
foo + +bar
which is the same as
foo.+(bar.+#())
So, as you can see, the line
level++
on its own is not syntactically invalid. It is the end on the next line that makes this invalid. Which is exactly what the error message says: you are using the unary prefix + operator, so Ruby is expecting the operand, but instead finds an end it was not expecting.

Ruby break expression acting weird [duplicate]

This question already has answers here:
No increment operator (++) in Ruby? [duplicate]
(3 answers)
Closed 6 years ago.
require 'csv'
i = 0
CSV.foreach("survdata.csv", headers: true) do |row|
puts row
i++
if i > 1 then
break
end
end
This looks so simple, and yet it doesn't run. Can you see why I am getting:
/mydev/surveyresult/surveyresult.rb:11: void value expression
Ruby does not support i++ syntax as a shortcut to i+=1. See "Why doesn't Ruby support i++ or i-- (increment/decrement operators)?" for more information why.
You can fix your code like this:
require 'csv'
i = 0
CSV.foreach("survdata.csv", headers: true) do |row|
puts row
i = i+1
if i > 1 then
break
end
end
More information on the error message (thanks sawa):
Ruby does actually support i++ syntax. If it is followed by x, it is interpreted as unary operator + applied to x, whose result passed as an argument to i+. In your example, if i > 1 then; break; end does not return any value, hence the error message "void value expression".
Ruby doesn't have an increment operator the last time I looked.
In place of
i++
do
i += 1
Yes. It is because the:
if i > 1 then
break
end
part breaks, which does not have a return value (within the code block in question). And you cannot apply the unary operator +# to something that lacks a value, nor can i.+ take the return value of such as an argument.

Basic URL opener in Ruby

I'm trying to create a simple ruby script that opens a bunch of URLs in Bing by looping through simple searches of the numbers 1-40, but when I run this in terminal I get:
"undefined method `<' for nil:NilClass (NoMethodError)"
#!/usr/bin/ruby
num = 0
target = 40
while start < target do
open("http://www.bing.com/search?q=" + $num)
num += 1
end
(Sorry if it's some simple mistake, this is my first ruby program.)
Update: **
Ok, thanks for catching that!
now it's giving me this error:
`+': can't convert Fixnum into String (TypeError)
how do I incorporate the two? Is there some type of parser like in Java?
Thank you Arup and Mischa!
Just do as below to fix your code :
while $num < $target do
open("http://www.bing.com/search?q=#{$num}")
$num += 1
end
You didn't define any where the variable $start. I think you should use there $num. I would recommend to use only local variable for this purposes, like num,target. Don't need global variables.
open("http://www.bing.com/search?q=" + $num) also wouldn't work. As you are trying to concat a number with a string. Either convert the number to a string using #to_s or use string interpolation, as I did below.
Without global variable write as :
while num < target do
open("http://www.bing.com/search?q=#{num}") # better
# or write as open( "http://www.bing.com/search?q=" + num.to_s )
num += 1
end

Why don't the following Ruby methods work? I've written a couple of methods that are supposed to give the sum of an entered array

This is what's up:
It seem I've got a syntax problem. Both of the following methods, which are similar to one another, load to irb fine. When I go to use them, though, they produce errors. Since I'm just learning this, I'm not only looking for a fix, I'm looking to understand why both return errors and how any fix works to solve the issues.
Thanks for the help,
TJ
First method:
def sum(*)
i = 1
total = sum[0]
until sum[i] == nil
total = total + sum[i]
i += 1
end
puts total
end
Upon loading this file irb returns => nil, no errors. However, an attempt to use the method looks like:
sum 3, 58, 298, 2
Unknown error.
Writing the method directly in irb vs loading .rb file produces this error after line 3:
def sum(*)
.. i = 1
.. total = sum[0]
(eval):2: (eval):2: compile error (SyntaxError)
(eval):2: syntax error, unexpected $end, expecting kEND
total = sum[0]
^
Now, I see that it says SyntaxError but I do not know what the rest of the feedback means nor what proper syntax for this would be.
Second method:
def sum(*)
i = 1
total = sum[0]
until i == sum.count
total = total + sum[i]
i += 1
end
puts total
end
This one produces all the same errors in the same ways as the first.
Try this instead:
def sum(*nums)
sum = 0
nums.each { |num| sum += num }
sum
end
sum(1, 2, 3)
I don't think `def sum(*) is valid Ruby syntax; you have to give your vararg a name.
Also, see this Stackoverflow question for an even shorter way to sum an array of numbers.

Resources