2012-06-04 41 views
1
class X 
    class << self 
    def attr_string arg 
     eval("def #{arg}; return #{arg.to_s}; end") 
    end 
    end 
end 

是我正在使用的代碼。我試圖將它變成類宏,比如attr_accessor。當我打電話爲什麼我在此代碼中獲取SystemStackError?

foo = 50 
X.attr_string :foo 
X.foo 

我得到一個SystemStackError。爲什麼是這樣?

+0

'X.foo'應該返回什麼?在你的情況下,它應該返回'foo' – fl00r

回答

0
class X 
    def attr_string arg 
    (class << self; self; end).class_eval do 
     define_method arg do 
     arg 
     end 
    end 
    end 
end 

或少許清潔劑

class X 
    def self.attr_string arg 
    self.class.instance_eval do 
     define_method(arg) { arg.to_s } 
    end 
    end 
end 
+0

X.foo返回'foo'而不是50. – Anil

+0

@Anil,在他的代碼中他不是返回50,而是foo(如果他的代碼可以工作;)) – fl00r

+0

我想他從來沒有經過循環。爲了返回foo,你不必調用X.他將50分配給foo的事實可能意味着他正試圖恢復50。只有他和他可以告訴。 – Anil

0

無限遞歸將做到這一點。

選項1(使用類變量):

@@foo = 50 

class X 
    def X.attr_string arg 
    eval("def X.#{arg.to_s}; return @@#{arg.to_s}; end") 
    end 
end 
X.attr_string :foo 
X.foo 

選項2(指定值而定義方法):

class X 
    def X.attr_string arg, val 
    eval("def X.#{arg.to_s}; #{val}; end") 
    end 
end 
X.attr_string :foo, 50 
X.foo 

我想return foo嘗試再次運行FOO的方法,無限。但即使您命名了變量foo1並返回了foo1,它也不會將foo1視爲類變量,因爲它已經丟失了範圍。

您可以嘗試將值包裝在lambda或編組foo對象中。如果您有此運氣,請發佈所有結果。

有趣的問題!

+0

仍給我systemstackerr –

+0

我編輯了答案並進行了測試。這更接近你想要的嗎? – Anil

相關問題