Ruby << syntax method raises an error, but .push method not when using yield. Why?

Viewed 63

I am trying to figure out why the case C is not working. As you can see when I use 'yield' and '<<' sugar syntax it raises an error, but if I use the method's name 'acc.push' it works. In the other hand, if I use the 'result' variable to get yield result and then add to acc array using << syntax, it works. I just would like to understand why it does not work in the case C. Thanks.

Case A - Working fine

def my_map(my_arr)
    c = 0 # the counter
    acc = [] # new array
    until c == my_arr.length
        acc.push(yield my_arr[c])
        c += 1
    end
    acc
end
p my_map( [1,2,3,4] ) { |each| each * 10 }

Case B - Working fine

def my_map(my_arr)
    c = 0 # the counter
    acc = [] # new array
    until c == my_arr.length
        result = yield my_arr[c]
        acc << result
        c += 1
    end
    acc
end
p my_map( [1,2,3,4] ) { |each| each * 10 }

Case C - Error: syntax error, unexpected local variable or method, expecting `end' acc << yield my_arr[c]

def my_map(my_arr)
    c = 0 # the counter
    acc = [] # new array
    until c == my_arr.length
        acc << yield my_arr[c]
        c += 1
    end
    acc
end
p my_map( [1,2,3,4] ) { |each| each * 10 }
3 Answers

While you expect that Ruby interprets acc << yield my_arr[c] as

acc.<<(yield(my_arr[c]))

Ruby actually understands it like this

acc.<<(yield)(my_arr[c])

Which doesn't make much sense. It can be fixed by using parentheses as others already mentioned:

acc << yield(my_arr[c])

You're hitting a case of operator precedence, which Ruby can't resolve for itself.

You can fix it by using parentheses to provide enough clarity for Ruby to work out how to parse the offending line:

acc << yield(my_arr[c])

Just use parenthesis for the yield method call.

acc << yield(my_arr[c])

My guess is that the << tries to add the yield directly to the array which results in the syntax error.

Related