2014-01-10 54 views
3

如果我有一個類:instance_eval的不DO /結束塊工作,只能用{} -blocks

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)

爲什麼我不能用instance_eval來使用do/end塊?

P.S.我正在使用Ruby 2.1.0。

+1

這裏工作(紅寶石2.0.0)你使用的是什麼紅寶石版本? – levinalex

+0

適合我(2.1.0)。你確定你粘貼的代碼導致錯誤? –

+0

無法在1.9.3中重現。如果你有一些較老的/不同的Ruby實現,它可能與'do..end'塊的優先級較低,然後是'{..}'塊有關。 –

回答

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(塊)。