4

私の機能は次のとおりです。

def hello(str)
  puts "hello #{str}"
end

def hello_scope(scope, &block)
  # ???
end

メソッドのブロック内で関数を一時的に拡張したいと思います。

では、元のメソッドに渡す前に、文字列をhello_scope前に追加したいだけです。次に例を示します。scopestrhello

hello 'world'               #=> hello world

hello_scope "welcome!" do
  hello 'bob'               #=> welcome!hello bob
  hello 'alice'             #=> welcome!hello alice
end

Rubyでこの種のことになると、私は一種の初心者です。誰かが私がこれをエレガントな方法で解決するのを手伝ってもらえますか?


編集:

作業が簡単になる場合は、次のように、メソッドを引数としてブロックに渡しても問題ありません。

hello_scope "welcome!" do |h|
  h "bob"                     #=> welcome!hello bob
  h "alice"                   #=> welcome!hello alice
end
4

2 に答える 2

4

1 つの方法は、ブロックがインスタンス評価される「評価コンテキスト オブジェクト」を作成することです。このオブジェクトは、ブロックに固有のすべてのメソッドを提供する必要があります。以下の例では、グローバル メソッド「hello」を明示的に参照する方法を覚えていないため (無限再帰を避けるため)、同じ名前を使用しませんでした。適切なライブラリでは、「hello」はどこかでクラス メソッドとして定義されるため、問題にはなりません。

例えば

def hello(str)
  puts "hello #{str}"
end
class HelloScope
  def h(str)
    print scope
    hello(str)
  end
end
def hello_scope(scope, &block)
  HelloScope.new(scope).instance_eval(&block)
end
于 2013-03-22T07:25:10.157 に答える
0

現在のスコープを考慮して「hello」メソッドを変更するだけです。

class Greeter
  def initialize
    @scope = nil
  end

  def hello(str)
    puts "#{@scope}hello #{str}"
  end

  def with_scope(scope)
    @scope = scope
    yield
    @scope = nil
  end
end

Greeter.new.instance_eval do
  hello 'world'               #=> hello world

  with_scope "welcome!" do
    hello 'bob'               #=> welcome!hello bob
    hello 'alice'             #=> welcome!hello alice
  end
end
于 2013-03-22T08:14:02.077 に答える