Ruby Syntax Sugar on Addition Methods - ruby

Quick question, why this doesn't work?
sum = {}
e = "a"
(sum[e] ||= 0) += 1
I got (expecting 1):
SyntaxError: unexpected tOP_ASGN, expecting $end
(sum[e] ||= 0) += 1

When you do (sum[e] ||= 0) the parentheses cause the expression to be evaluated. As a result, it'll evaluate to the value of sum[e] (e.g. 0), which you cannot do a += operation on. It won't return an lvalue/reference to sum[e] as you might expect.
You can verify this by doing the same operation on what would be the result:
irb(main):001:0> 0 += 1
SyntaxError: (irb):1: syntax error, unexpected tOP_ASGN, expecting $end
Or even something like this:
irb(main):004:0> (sum[e]) += 1
SyntaxError: (irb):4: syntax error, unexpected tOP_ASGN, expecting $end
If for some reason you want to keep it on one line, you can do something like this:
sum[e] ||= 0; sum[e] += 1
As dbenhur mentioned, if you are going to be doing this a lot, you can also set a default value for all keys in the hash:
sum = Hash.new(0)
Sets sum to be a hash where every key is automatically set to 0 when you access it.

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

Why won't this simple ruby method run on my local environment?

I am trying to run the following simple method in my local environment, and I cannot figure out what is wrong with it
def test_counter(max)
i = 0
count = 0
while count < max
if i != 0
count = i**2
i++
end
end
puts i
end
test_counter 50
I get these errors:
practice.rb:9: syntax error, unexpected keyword_end
practice.rb:35: syntax error, unexpected end-of-input, expecting keyword_end
There is no i++ in ruby; use i += 1. Also i will never equal something beside 0 so if i != 0 does not work

Ruby If Elsif Else block syntax

What's wrong with this block?
if item.nil?
found = true
elsif item[:name] == name && item[:category] == category
found = true
else
i++
end
When I do syntax checking, I get
syntax error, unexpected keyword_end
but if I delete end then I get
syntax error, unexpected end-of-input
The problem is here:
i++
Ruby doesn't have a ++ operator. What you want is this:
i += 1
I believe the reason for that specific error is that Ruby is interpreting the second + as a unary + operator, i.e. the "positive number sign" (because it's the only thing that makes sense in that context), and so expects the next token to be a number†, e.g. (parentheses for clarity):
i + (+5)
...but the next token is end, ergo the syntax error.
†Or something else that responds to the +# method.

Ruby: unexpected end-of-input, expecting keyword_end for if statement

I was working with Java for a few months and am transitioning back to Ruby now. I am getting a weird error from the following code:
def count_divisors
divisor_hash = {}
25.times do |i|
divisor_hash[i] = find_dividends(i)
end
puts divisor_hash
end
def find_dividends(i)
count = 0
1000.times do |k|
if i % ( k + 1 ) == 0
count++
end
end
count
end
count_divisors()
This code is generating the following error:
test.rb:14: syntax error, unexpected keyword_end
test.rb:19: syntax error, unexpected end-of-input, expecting keyword_end
This error does not occur when I remove the if statement. I am not sure why. I know every if statement needs an end statement, for some reason it seems upset by the placement of that end statement though.
Change the count++ to count += 1 Ruby does not support incremental operator.

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