2

Clojureでこのような関数呼び出し(my-function [abc])を書くとき。Clojureはどのようにして私の機能を見つけますか?グローバル/名前空間ごとのシンボルテーブルからのルックアップを実行しますか?

シンボルテーブルは、ルックアップにO(1)時間計算量を提供するハッシュテーブルとして実装されていると想定しています。また、文字列としての関数名を、O(n)時間かかるテーブルのシンボルと比較する必要があります(nはシンボルの長さです)。これは、シンボルが長いほど、名前解決が遅くなることを意味します。それが正しいか?

4

3 に答える 3

3

Clojureはコンパイルされた言語であり、JVMバイトコードに直接コンパイルされますが、完全に動的なままです。

-http ://clojure.org/のフロントページから

コンパイルとは、シンボルがすでに事前にハッシュされていることを意味します。関数名の長さに関する2番目のステートメントは、コンパイル時にのみ真になります。また、すべてのCPUサイクルについて懸念している場合、JVM/CLR言語はさまざまな理由で友だちにはなりません。

于 2012-10-26T18:02:43.320 に答える
3

==シンボルはインターンされた文字列を使用するため、。ではなく、と比較されます.equals。つまり、あなたが言った部分でさえO(n)はO(1)です。ただし、これらのルックアップはすべて(a)とにかく非常に高速であり、(b)実行時ではなくコンパイル時に行われるため、ほとんど問題になりません。プログラムを実行すると、すべての関数呼び出しがポインターの逆参照またはその類似物に解決されます。

于 2012-10-26T18:47:18.963 に答える
2

ns-map名前空間は実際にマップとして動作し、次の関数を使用して名前空間を直接確認できます。

autotestbed.core> (pprint (take 5 (ns-map *ns*)))
nil
([sorted-map                                                                                               
  #<Var@6899a7ce:                                                                                          
    #<core$sorted_map clojure.core$sorted_map@5875c014>>]                                                  
 [read-line                                                                                                
  #<Var@1de9e86e: #<core$read_line clojure.core$read_line@57c00972>>]                                      
 [re-pattern                                                                                               
  #<Var@74064c7b:                                                                                          
    #<core$re_pattern clojure.core$re_pattern@37d02427>>]                                                  
 [keyword?                                                                                                 
  #<Var@4798088a:                                                                                          
    #<core$keyword_QMARK_ clojure.core$keyword_QMARK_@630b813f>>]                                          
 [hta-deploy-cmd                                                                                           
  #<Var@7a7bce95:                                                                                          
    #<core$hta_deploy_cmd autotestbed.core$hta_deploy_cmd@6a6a782d>>])

より具体的には、変数をオブジェクトにマップします。

関数をそのvarでルックアップして、変更がプログラム全体に即座に伝播するようにしたい場合は、コンパイル時にvarに含まれていた関数の代わりに、varを呼び出すことができます。これにより、すべての呼び出しでルックアップが行われます。

(#'foo 4) looks the function up in the var every time
(foo 4) looks it up in the map once when it's compiled.   
于 2012-10-26T18:01:51.987 に答える