Странная ошибка Proc в Ruby - PullRequest
       0

Странная ошибка Proc в Ruby

3 голосов
/ 12 сентября 2011

У меня есть метод, принимающий лямбду, которая будет вызвана, или строка, которая будет оценена.Почему следующий метод не работает:

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

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

Но этот работает:

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

test 'puts 1'
# => 1

Ответы [ 2 ]

3 голосов
/ 12 сентября 2011

Здесь:

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

В результате вы получите Proc в expr, который является закрытием над expr, поэтому, когда Proc оценивается, он пытается eval сам, потому что expr внутри лямбды находится сама лямбда.

Здесь:

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

замыкание превышает foo, что относится к исходному строковому значению expr, поэтому нетПричудливая путаница с ссылками на себя, и вы в конечном итоге будете использовать eval в строке.

3 голосов
/ 12 сентября 2011

Вы назначаете лямбду переменной expr. Эта лямбда пытается вычислить содержимое переменной expr (т.е. пытается вычислить себя). eval ожидает только строку, поэтому возникает исключение.

...