2014-01-10 3 views
3

Если у меня есть класс:Instance_eval не работает с делать/конец блока, только с {} -блоков

class KlassWithSecret 
    def initialize 
    @secret = 99 
    end 
end 

и запустить:

puts KlassWithSecret.new.instance_eval { @secret } 

печатает 99, но если я бегу :

puts KlassWithSecret.new.instance_eval do 
    @secret 
end 

возвращает ошибку: `instance_eval': wrong number of arguments (0 for 1..3) (ArgumentError)

Почему я не могу использовать блоки do/end с instance_eval?

P.S. Я использую Ruby 2.1.0.

+1

работает здесь (ruby 2.0.0) какая рубиновая версия вы используете? – levinalex

+0

Работает для меня (2.1.0). Вы уверены, что код, который вы вставили, вызывает ошибку? –

+0

Не воспроизводить в 1.9.3. Если у вас есть более старая/разная реализация Ruby, это может быть связано с более низким приоритетом блока 'do..end', а затем' {..} 'block. –

ответ

4

Это потому, что, когда вы передаете блок с фигурными скобками, он передается instance_eval методы. Но если вы передаете его с do-end, он передается методу puts, поэтому instance_eval не получает блок и вызывает ошибку.

5

Вставить скобки в puts, потому что более низкий приоритет do..end блок.

puts(KlassWithSecret.new.instance_eval do 
    @secret 
end) 

или использование бандаж синтаксис блока

puts KlassWithSecret.new.instance_eval { 
    @secret 
} 
3

Это связано с тем, что при использовании блока do..end блок передается функции puts. Код с блоком do..end будет работать, если вы напишете его так:

puts(KlassWithSecret.new.instance_eval do 
    @secret 
end) 
-1

Ruby (2.0.0) работает. Код:

KlassWithSecret.new.instance_eval do 
    p @secret 
end 
# 99 

никаких проблем.

+1

Это работает, потому что вам не хватает вызова 'puts'. – toro2k

+0

Я думаю глубоко. Я отправляю новый ответ. Надеюсь, что это может вам помочь. –

+0

@ toro2k Я думаю, что это код гольфа ... :) –

0
a = Proc.new {@secret} 
puts KlassWithSecret.new.instance_eval(&a) 
# 99 

Следует сказать, что puts KlaccWithSecret do @secret end не получает Proc (блок).