Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Weird Proc error in Ruby

I have a method accepting a lambda which will be called or a string which will be evaluated. Why does the following method fail:

def test(expr)
  expr = expr.respond_to?(:call) ? expr : ->{ eval(expr) }
  expr.call
end

test 'puts 1'
# => TypeError: can't convert Proc into String

But this one work:

def test(expr)
  foo = expr
  expr = expr.respond_to?(:call) ? expr : ->{ eval(foo) }
  expr.call
end

test 'puts 1'
# => 1
like image 285
Mario Uher Avatar asked Jul 30 '26 09:07

Mario Uher


2 Answers

In here:

expr = expr.respond_to?(:call) ? expr : ->{ eval(expr) }

You end up with a Proc in expr that is a closure over expr so when the Proc is evaluated, it tries to eval itself because the expr inside the lambda is the lambda itself.

In here:

foo  = expr
expr = expr.respond_to?(:call) ? expr : ->{ eval(foo) }

the closure is over foo which refers to the original String value of expr so there is no funky self-referential confusion and you'll end up using eval on a String.

like image 157
mu is too short Avatar answered Aug 01 '26 06:08

mu is too short


You are assigning lambda to variable expr. That lambda tries to eval content of variable expr (i.e. tries to eval itself). eval expects only string, that is why exception is raised.

like image 41
Victor Deryagin Avatar answered Aug 01 '26 06:08

Victor Deryagin



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!