Rubyブロック、Procs、Instance_Eval
-
28-10-2019 - |
質問
私は最近、これに似たことをしようとしました:
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であるということです。しかし、これを持っていることには明らかに特別なことがあります &
アンパサンド...
誰かが私にこれを説明できますか?これについて特別なのは、通常のProcを何でも変換することは可能ですか &block
物体?
編集
私の2番目の質問を見つけたばかりで、Prepend An &
Procに...それは簡単でしたが、これは本当に何をしていますか?
解決
最初の例を操作するためにしなければならないのは、これだけです:
>> a.instance_eval &b #=> "SOME STRING"
その理由はそれです instance_eval
文字列またはブロックのいずれかが必要で、アンパサンドは後者を提供します。
ブロックとProcsの違いを理解するために、おそらく次のブログ投稿が役立ちます。
他のヒント
違いはそれです a.instance_eval b
通過しています b
instance_evalへの定期的な議論として a.instance_eval &b
ブロックとして渡しています。これらは2つの異なるものです。
このメソッド呼び出しを検討してください。
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のインスタンスであることは関係ありません。構文は、メソッドによってどのように渡され、処理されるかを決定します。
Instance_Evalが評価する文字列またはブロックを受け入れるためです。 instance_eval(&block)
あなたを追い越しています block
instance_evalへのブロックとして。
重要な違いはそれです Procインスタンスはオブジェクトです 一方 ブロックはオブジェクトではありません. 。 &
オペレーターです ブロックとPROCインスタンスを交換します 互いに。
メソッドに対するすべての引数はオブジェクトでなければなりません。引数に加えて、方法はブロックを取ることができます。 instance_eval
文字列引数またはブロックのいずれかを取る方法です。 PROCオブジェクトを渡すと、どちらのケースも満たされません。添付する場合 &
PROCオブジェクトには、ブロックとしてヘンゲル化されます。
これは機能します:
a = "some string"
b = Proc.new{ upcase }
a.instance_eval &b
instance_eval
メソッドはブロック引数を受信できます。b
aです Proc
.