2012-05-22 6 views
5

Common Lispでハッシュテーブルを初期化するための移植性の高い方法を探しています。例えば。定数ハッシュテーブルで動作するものだけでなく、可変ハッシュをあらかじめロードすることもできます。 CLISPでは、私は以下を使用しています:Common Lisp:多くのエントリを持つハッシュテーブルを簡略化する

(defconstant +my-map+ #S(HASH-TABLE :TEST FASTHASH-EQ 
    (key1 . "value1") 
    ... 
    (keyN . "valueN") 
)) 

このフォーマットは残念ながらCLISPでしか動作しません。

+0

https://github.com/vseloved/rutils/ blob/master/core/readtable.lisp#L10 –

+0

たとえば、次のように注意してください。 http://www.aiai.ed.ac.uk/~jeff/lisp/cl-pitfallsは、 'defconstant'フォームの値としてハッシュテーブルを使用することを警告します。 – Hugh

+0

ありがとうございました。この基本的な機能は標準では欠けており、何らかの形で追加する必要があります。 PerlやPHPを模倣する新しい構文を導入するのではなく、make-hash-tableをラップし、オプションを追加するマクロを書くことについてどう思いますか?たとえば、make-arrayなどの標準でサポートされている同じオプションのinitial-contents?私はこれがおそらく非常に効率的ではないと思います。なぜなら、コンテンツは横断されなければならないalistによって指定されるだろうが、少なくともLisp構文と一貫しているからです。 –

答えて

6

一つは、プログラムの読み取り時にハッシュテーブルを構築することができます。

(defvar *ht* #.(let ((ht (make-hash-table))) 
       (loop for (key . value) in 
         '((a . 1) (b . 2) (c . 3)) 
         do (setf (gethash key ht) value)) 
       ht)) 

(describe *ht*) 

#.は、読み出し時間の評価のために使用されます。コンパイラは、ハッシュテーブルをFASLファイルにダンプします。

これは、その後コンパイルすることができます:SBCLを使用して

* (compile-file "/tmp/test.lisp") 

; compiling file "/private/tmp/test.lisp" (written 24 MAY 2012 10:08:49 PM): 
; compiling (DEFVAR *HT* ...) 
; compiling (DESCRIBE *HT*) 

; /tmp/test.fasl written 
; compilation finished in 0:00:00.360 
#P"/private/tmp/test.fasl" 
NIL 
NIL 
* (load *) 

#<HASH-TABLE :TEST EQL :COUNT 3 {100299EA43}> 
    [hash-table] 

Occupancy: 0.2 
Rehash-threshold: 1.0 
Rehash-size: 1.5 
Size: 16 
Synchronized: no 
T 
* *ht* 

#<HASH-TABLE :TEST EQL :COUNT 3 {100299EA43}> 

ハッシュテーブルを作成する関数として:

(defun create-hashtable (alist 
         &key (test 'eql) 
         &aux (ht (make-hash-table :test test))) 
    (loop for (key . value) in alist 
     do (setf (gethash key ht) value)) 
    ht) 
+1

ありがとうReiner!唯一の欠点は少し冗長ですが、それはマクロを使うことで助けられます。私はLispの初心者であり、マクロはあまりよくありません。とにかく、これは私のものです: '(def(key-value)on、pair by# ') (ハッシュテーブル '(a1 b 2 c 3)))) –

+1

@AntonioBonifati(ハッシュテーブルの設定) :私は、マクロではなく、関数を書くことが疑わしいとき。マクロでなければならない理由はありませんか? –

+1

はい、ありがとう、私は知っています、その理由は、マクロは書き込みやデバッグが難しいということです。しかし、この場合に関数を書くと、#で呼び出すことはできません。少なくともECLでは、それは未定義であると私に伝えます。私はこれが#の効果だと思います。つまり、ユーザー定義関数は読み取り時に使用できません。私は:initial-contentsキーワード・パラメータを追加しながら、make-hash-tableを完全に構成できるようにマクロ・ラッパーを書くことができるのだろうかと思います。それは "標準にこの機能を追加"するでしょう:) –