web-dev-qa-db-ja.com

バイトコードウィービングとLISPマクロ

JavaやC#などの言語用に作成されたライブラリについて、関数呼び出しのインターセプトやロギングコードの挿入などを行うためにバイトコードのウィービングを利用しています。 LISP/Clojureマクロの利用方法をよりよく理解するために、マクロを読んでいます。マクロについて読むほど、マクロがバイトコードウィービングライブラリと同じ種類の機能を提供しているように見えます。機能とは、コンパイル時にコードを操作します。

私が見てきたライブラリの例は、AspectJ、PostSharp、Cecilなどです。

どちらか一方だけでできることはありますか?彼らは実際に同じ問題を解決しますか、それともリンゴとオレンジを比較していますか?

11
mortalapeman

バイトコードのウィービングとマクロは2つの異なるものです。

バイトコードウィービングは、関数呼び出しをインターセプトする方法です。そのため、関数の実行前または実行後に、ある種の機能(通常、ロギングなどの横断的関心事)を関数呼び出しに挿入できます。バイトコードのウィービングはバイトコードレベルで行われます。つまり、コンパイル後に発生します。関数自体は影響を受けません。これは アスペクト指向プログラミング が使用する手法の1つです。

マクロは、言語の構文を拡張する方法です。最も単純な形式では、マクロはキーストロークを記録し、ホットキーを使用してそれらを再生するための方法です。言語マクロも同様に機能します。キーワードまたはその他の構文構造は、ある種のマクロ展開の代わりになります。もちろん、これは単純化しすぎです。 LISPに特有のマクロのより良い例は here にあります。

10
Robert Harvey

同じ目的で使用される場合がありますが、LISPマクロはJavaバイトコードウィービングプラグインとはかなり異なります。LISPマクロは、LISP構文をLISPソースコードレベルで拡張します。LISPマクロは他のLISPコードと同じレベルで、一般的に使用される言語機能です。

Javaバイトコードウィービングプラグインは、JVMレベルで動作します。多くのJavaプログラマは他の人が作成したバイトコードウィービングプラグインを使用する場合がありますが、Javaプログラマが独自のバイトコードウィービングプラグインを作成することはほとんどありません。

Javaコンパイラプラグインによって実行される作業の一部は、動的言語で非常に簡単に実行できます。関数呼び出しのインターセプトは特に簡単です。

5
kevin cline

LISPマクロはソースコードレベルで動作しています。マクロをコードの一部にラップすると、多くのことができます。ソースコードの解析、コードの挿入、コードの書き換えなどを含みます。

関数呼び出しを変更する場合、LISPは通常2つのメカニズムを使用します。

  • 遅延バインディングシンボル。シンボルにバインドされた関数を変更できます。シンボルを通過するすべての関数呼び出しは、新しい関数を使用します。

  • LISP実装は、「アドバイス」と呼ばれる機能を提供する場合があります。これにより、呼び出しの前後、または前後でコードを実行できます。 LispWorksの例: Advice

したがって、低レベルのコード操作なしで呼び出しを傍受できます。

4
Rainer Joswig