たとえば、シンボルテーブルでそれを使用して検索するLispプログラムがある場合、それは「静的」言語の(eval 'sym)
ようなものよりも実際に優れたパフォーマンスを発揮しますか?aClass.getField("sym", anInstance)
3 に答える
それは言語の実装に依存します。
たとえば、aClass.getField( "sym"、anInstance)がevalとまったく同じであってはならない理由はまったくありません。
一方、実際の実装内でも速度は大きく異なります。たとえば、.Netには、低速の反射方法と高速の方法があります(多くの場合、100倍以上高速です)。そして、どれが必要かは、ほとんどの場合、メソッドで実際に何をしたいかによって異なります。値を読み取りたいだけですか?値を変更しますか?セキュリティは関係がありますか?
2つのアプローチが相互に排他的ではないこともあり、この問題は適切に提示されていません。
ちょうど例として、CommonLispはを提供しますEVAL
。
Common Lispはまた、パッケージ内のシンボルの確認、名前による(グローバル)変数の値の検索、名前によるクラスのインスタンスの構築、クラス内のスロットの値の検索または設定、または関数の呼び出しを可能にする多くのリフレクション機能を提供します彼らの名前に基づいています。広く実装されている(ANSI規格ではありませんが)CLOSメタオブジェクトプロトコルを使用すると、名前に基づいてクラスとジェネリック関数についてさらに詳しく知ることができます。
もちろん、実装ではなく言語のパフォーマンスを比較するという問題は残っています。当然、ネイティブコードにコンパイルされたCommon Lispは、解釈されているCommon Lispとはまったく異なるパフォーマンスを示し、ほとんどのCL実装では、コンパイルされたコードと解釈されたコードを混在させることができます(コンパイラーのみを提供するものもあります)。
一般に(バイトコードとネイティブコードまたはコード生成品質などのモジュロ実装の問題)、メタ言語的抽象化を備えた言語は、そのような抽象化を欠いた言語と同等の時間枠で作成できるプログラムよりも優れたプログラムを作成するためのより強力な機能を提供します。場合によっては、独自の言語の実装を作成すると、基本言語のコンパイラよりもはるかに強力な最適化を行うための情報が多くなります。実際には、これについて多くの例があります。
また、リフレクション(「オープン実装」の特定のケースである)とメタ言語的抽象化を混ぜ合わせているようです。メタ言語的抽象化とは、基本言語の上に新しい言語を構築することであり、リフレクション(または「オープン実装」)とは、プログラムの内部をプログラム自体に公開することです。
あなたの特定の例(もちろん、バイトコードとネイティブコードまたはコード生成品質のようなモジュール実装の問題)では、(eval 'sym)
おそらくより高速です。その理由は'sum
、文字列ではなくシンボルオブジェクトであるためです。シンボルを評価するということは、その値のセルを取得することを意味します。したがって、evalはいくつかのことを行うだけで済みます。
- オブジェクトタイプ(この場合はシンボル)でディスパッチします(たとえば、値タグを使用してジャンプテーブルを通過します)
- シンボルの値を抽出します(シンボル構造を逆参照することにより)
しかし、Javaの例にはもっとやるべきことがあります。
- 名前が付けられたフィールドを検索します。これには、たとえば、文字列のハッシュを計算し、ハッシュテーブルを使用する必要があります
- フィールドの値を抽出します(フィールドに固有のオフセットでインスタンスポインタを逆参照することにより)
- 値をボックス化します(参照でない場合)
特に高価な部分は、ハッシュを計算し、ハッシュテーブルを通過することです。