4

JavaScriptのバックグラウンドから来て、JavaScriptの動的スコープを使用して関数に値をカプセル化できるようになりました。例えば:

function Dog( firstname, lastname ) {

  this.fullname = firstname + lastname

  return {
    say_name: function () {
      return fullname;
    }
  }

}

今Rubyでは、このようなものがうまく機能するかどうかはわかりません。

class Foo

  attr_accessor :bar, :baz

  def initialize bar, baz
    @bar = bar
    @baz = baz
  end

  def give_me_a_proc
    return Proc.new { @bar + @baz }
  end
end

誰かがRubyでスコープがどのように機能するかについて簡単に説明できますか?から返されたProcを呼び出した場合give_me_a_procでも、定義時スコープにアクセスできますか?

また、procを定義すると値は固定Fooされますか、それとも定義された後でもProcに加えられた変更はProcに引き継がれますか?

4

4 に答える 4

4

はい、引き続き定義タイムスコープにアクセスできます。Procクラスのドキュメントを参照してください。

変更は、Procの事後定義に引き継がれます。irbの結果はクラスで実行されます。

> foo = Foo.new(1, 2)
 => #<Foo:0x007f9002167080 @bar=1, @baz=2> 
> quux = foo.give_me_a_proc
 => #<Proc:0x007f900214f688@(irb):11> 
> quux.call
 => 3 
> foo.bar = 3
 => 3 
> quux.call
 => 5 
于 2012-07-20T16:35:44.630 に答える
3

Rubyでは、procはクロージャです。Javascriptでは、関数はクロージャです。クロージャの考え方は、クロージャが定義された環境を「クロージャ」することです。Rubyでは、procの外部にあるコードでも、proc内の変数を変更でき、新しい値はproc内に反映されます(デモについては、peakxuを参照してください)。Javascriptクロージャがこのように機能するかどうかはわかりません。

于 2012-07-20T16:42:24.890 に答える
2

Rubyプロシージャとラムダはクロージャです。あなたがそうするとき、return Proc.new { @bar + @baz }あなたは本当にキャプチャしていますself、それはインスタンス変数が検索される方法です。Rubyブロックもクロージャです。Rubyでは変数を変更できます。呼び出し元のスコープがまだ存在していると仮定すると、変更は呼び出し元のスコープまで伝播されます。

@hi = 0
def get_hi()
  lambda {@hi = 42}
end
get_hi.call()
@hi #=> 42

注:procに非常に緩い引数要件がない限り(引数を取得するかどうか、Cのようにいくつあるかは関係ありませんint f(void))、のlambda代わりに使用してProc.newください。lambda正しい数の引数を取得することを確認するためにチェックします。

于 2012-07-20T16:55:51.220 に答える
1

Rubyには、オブジェクトからクロージャーを取得するメソッドがあります。これは、例に非常に適しています。

class Foo
  # reopen Foo class
  def get_sum
    @bar + @baz
  end
end

m = Foo.new(5,20).method(:get_sum)
m.call #=> 25

はオブジェクトでありm、インスタンスのMethodクロージャとして機能するFooため、インスタンス変数との値はself引き続き使用できます。

于 2012-07-20T17:22:36.543 に答える