なぜ出力が異なるのですか?
ruby の proc にはレキシカル スコープがあります。これは、定義されていない変数が見つかった場合、呼び出されたのではなく、プロシージャが定義されたコンテキスト内で解決されることを意味します。これにより、コードの動作が説明されます。
ブロックが正規表現の前に定義されていることがわかります。これは混乱を招く可能性があります。問題は魔法の ruby 変数に関係しており、他の変数とはまったく異なる働きをします。@JörgWMittagを引用
それはかなり単純です。$SAFE がグローバル変数から期待されるように動作しない理由は、それがグローバル変数ではないからです。魔法のユニコーンの事だアマジギーです。
Ruby には魔法のようなユニコーンのようなものがありますが、残念ながらそれらは十分に文書化されていません (実際、まったく文書化されていません)。これは、別の Ruby 実装の開発者が難しい方法を発見したためです。これらのことはすべて異なる動作をし、(一見) 一貫性がありません。共通しているのは、グローバル変数のように見えますが、そのようには動作しないという 2 つの点だけです。
ローカル スコープを持つものもあります。スレッド ローカル スコープを持つものもあります。誰にも割り当てられずに魔法のように変化するものもあります。通訳者にとって魔法のような意味を持ち、言語の振る舞いを変えるものもあります。他の奇妙なセマンティクスが付加されているものもあります。
$1
および変数がどのように機能するかを本当に知りたい場合は、$2
見つけることができる唯一の「ドキュメント」はrubyspec であると思います。これは、 Rubinusの人々によって困難な方法で行われた ruby の仕様です。素敵なハッキングがありますが、痛みに備えてください。
$1、$2 変数を正しい方法で設定して、ブロックを別のコンテキストから gsub に渡す方法はありますか?
この次の変更で、あなたが望むものを達成することができます(しかし、あなたはすでにそれを知っているに違いありません)
require 'pp'
def hello(z)
#z = proc {|m| pp $1}
"hello".gsub(/(o)/, &z)
end
z = proc {|m| pp m}
hello(z)
その場でprocのスコープを変更する方法を知りません。しかし、あなたは本当にこれをしたいですか?