6

私は Ruby ブロックがどのように機能するかを理解しようとしており、そのために C でそれらを実装しようとしています。

クロージャを実装する簡単な方法の 1 つはvoid*、クロージャ/関数に囲んでいるスタックに a を渡すことですが、Ruby ブロックは、ブロックを使用するスコープからの return ステートメントと break ステートメントも処理するようです。

loop do
  break i if (i >= 4000)
  i *= 2
end

Java のクロージャー提案の 1 つもこのように機能すると思います。

では、Ruby ブロック/Java クロージャーを C でどのように実装しますか?

4

3 に答える 3

10

クロージャーの概念には、コンテキストの概念が必要です。C のコンテキストはスタックと CPU のレジスタに基づいているため、ブロック/クロージャを作成するには、スタック ポインタを正しい (および再入可能な) 方法で操作し、必要に応じてレジスタを保存/復元できる必要があります。

インタプリタや仮想マシンがこれを行う方法は、context構造体または類似のものを持ち、スタックとレジスタを直接使用しないことです。レジスタ ベースの VM を設計している場合、この構造はスタックとオプションでいくつかのレジスタを追跡します。少なくとも、これが最も簡単な方法です (ただし、実際に物事を正しくマッピングするよりもパフォーマンスは若干劣ります)。

于 2008-08-21T14:53:49.933 に答える
3

私は実際にこれを実装していないので、塩の袋でそれを取ってください.

クロージャには、データ環境とコード環境の 2 つの部分があります。あなたが言ったように、おそらくデータへの参照を処理するために void* を渡すことができます。おそらく setjmp と longjmp を使用して、Ruby ブレークに必要な非線形制御フロー ジャンプを実装できます。

クロージャーが必要な場合は、実際にそれらをサポートする言語でプログラミングする必要があります。:-)

更新: Clang で興味深いことが起こっています。彼らは C のクロージャのプロトタイプを作成しまし

于 2008-09-01T16:18:19.737 に答える
2

「RailswithPassion」コースの一部として、RubyBlocksに優れたスライドのセットがあります。

Ruby_Blocks.pdf

これは、ブロックの表現、それらがどのように引数を渡されて実行されるか、さらにはProcオブジェクトのようなものにまで及ぶことをカバーしています。それは非常に明確に説明されています。

次に、JRubyの人がJavaへの解析でこれらをどのように処理したかを調べることは興味深いかもしれません。codehausのソースを見てください。

于 2008-08-22T12:07:59.980 に答える