16

私は最近、これに似た何かをしようとしました:

a = "some string"
b = Proc.new{ upcase }
a.instance_eval b

エラーが発生します:

TypeError:Procを文字列に変換できません

しかし、これは機能します:

def b(&block)
  "some string".instance_eval &block
end

b{ upcase }

この方法の詳細:

def b(&block)
  "some string".instance_eval block
end

同じProc to Stringエラーが発生します。

だから...ブロックについての私の理解は、それらが単なるprocであるということです。&しかし、このアンパサンドを持つことには明らかに特別なことがあります...

誰かが私にこれを説明できますか?&block通常のprocをこのオブジェクトの特別なものに変換することは可能ですか?

編集

私の2番目の質問を理解し&、procの前に追加します...それは簡単でしたが、これは実際に何をしているのでしょうか?

4

5 に答える 5

24

最初の例を機能させるために必要なことは、次のとおりです。

>> a.instance_eval &b #=> "SOME STRING"

その理由はinstance_eval、文字列またはブロックのいずれかが必要であり、アンパサンドが後者を提供するためです。

于 2011-06-16T13:29:18.097 に答える
11

違いは、通常の引数として instance_eval に渡すのに対しa.instance_eval b、ブロックとして渡すことです。それらは2つの異なるものです。 ba.instance_eval &b

次のメソッド呼び出しを検討してください。

obj.foo(bar) do |x| 
  stuff(x) 
end

fooこれにより、1 つの通常の引数 ( bar) と 1 つのブロック引数 ( ) を使用してメソッドが呼び出されますdo |x| stuff(x) end&メソッド定義では、ブロック パラメーターの前に付けることで区別されます。

def foo(arg, &block)

また、リテラル ブロックの代わりに変数式を渡したい場合は、式の前に&を付けることで同様に実現できます (これにより Proc が生成されます)。

&noを指定して引数を渡すと、ブロックスロットではなくargスロットに入ります。引数がたまたま Proc のインスタンスであることは問題ではありません。構文は、メソッドによってどのように渡され、処理されるかを示します。

于 2011-06-17T02:36:09.610 に答える
1

重要な違いは、Procインスタンスはオブジェクトであるのに対し、ブロックはオブジェクトではないということです。は、ブロックとProcインスタンスを相互に交換&する演算子です。

メソッドへのすべての引数はオブジェクトでなければなりません。引数に加えて、メソッドはブロックを取ることができます。instance_evalString引数またはブロックのいずれかを取るメソッドです。Procオブジェクトを渡すと、どちらの場合も満たされません。&Procオブジェクトにアタッチすると、ブロックとして処理されます。

于 2011-06-16T13:42:09.707 に答える
1

これは、instance_evalがevalまたはブロックへの文字列を受け入れるためです。あなたをブロックとしてinstance_evalにinstance_eval(&block)渡します。block

于 2011-06-16T13:27:27.800 に答える
0

これはうまくいきます:

a = "some string"
b = Proc.new{ upcase }
a.instance_eval &b

メソッドはinstance_evalブロック引数を受け取ることができます。 bですProc

于 2013-08-11T08:05:33.117 に答える