2012-12-07 4 views
2

Proc 클래스를 확장하여 해당 생성자가 인수의 해시를 가져올 수 있도록하고 일부 메타 프로그래밍 구성으로 메소드로 변환됩니다. 의 효과에 뭔가 :원숭이 루비의 패치 및 오버로드 메서드

p = Proc.new(this: 100, that: 200, yes: 1, no: 2) { |arg| arg.even? } 
p.call(1) # => false 
p.this # => 100 
p.yes # => 1 

는이 같은 일을의 루비 방법을 알고 싶어요. 메타 프로그래밍없이

답변

3
class Proc 
    def initialize h; @h = h end 
    def method_missing k; @h[k] end 
    def respond_to_missing?; true end 
end 

p = Proc.new(this: 100, that: 200, yes: 1, no: 2) { |arg| arg.even? } 
p.call(1) # => false 
p.this # => 100 
p.yes # => 1 
+0

감사합니다. 나는 4 분 안에 이것을 받아 들일 것이다 ... –

+1

나는'def method_missing (k, * args); @ h.fetch (k) {super}; 끝 '대신. – akuhn

+2

'method_missing'을 정의 할 때 항상'respond_to_missing? '도 구현하는 것이 가장 좋습니다. –

2

:

require 'ostruct' 

r = OpenStruct.new(this: 100, that: 200, yes: 1, no: 2) 
def r.call(n) 
    n.even? 
end 

p r.this # 100 
p r.call(1) # false 

편집 : 마크 - 앙드레 Lafortune이 Openstruct에 대해 같은 생각을했다 @; 그의 구현 방식이 나아졌습니다.

3

당신은 (아마도이 ​​경우에한다) 원숭이 to_proccall을 구현하여 PROC 같은 동작합니다 자신의 클래스 을함으로써 모두 패치를 피할 수 있습니다. 예를 들어, OpenStruct부터 시작할 수 있습니다.

require 'ostruct' 
class MyFunkyClass < OpenStruct 
    def initialize(h, &block) 
    @block = block 
    super 
    end 

    def to_proc 
    @block 
    end 

    def call(*args) 
    @block.call(*args) 
    end 
end 

f = MyFunkyClass.new(this: 100, that: 200, yes: 1, no: 2) { |arg| arg.even? } 
f.that # => 200 
f.call(42) # => true 
[1,2,3,4].select(&f) # => [2, 4] 
+0

+1 블록을 오른쪽으로 가져 가기 위해 (나를 위해) 턱 떨어 뜨리기 마지막 예. – steenslag

+0

마지막 예제는'& : even? '이 작동하는 것과 같은 이유로 작동합니다; 'Symbol # to_proc'을 확인하십시오. –