2012-05-22 40 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的宏,並添加了以下選項:initial-contents,這是標準中所支持的相同選項,例如make-array?我認爲這不會很有效率,因爲內容將由必須遍歷的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初學者,不擅長宏。無論如何,這是我的:'(defmacro ini-hash-table(pairs) '(let((hash(make-hash-table:test'equal))) cddr do(setf(gethash key hash)value))hash))'Then then I do:'(defvar * ht *#。(ini-hash-table'(a 1 b 2 c 3)))' –

+1

@AntonioBonifati :當我懷疑寫一個函數,而不是一個宏。沒有理由它應該是宏觀的,是嗎? –

+1

是的,謝謝,我知道,一個很好的原因是宏很難編寫和調試。但是如果我在這種情況下寫一個函數,我不能用#來調用它。至少在ECL中它告訴我它是未定義的。我認爲這是#的效果。即任何用戶定義的函數在讀取時都不可用。我想知道是否可以編寫一個宏包裝器,允許在添加:initial-contents關鍵字參數的同時完全配置make-hash-table。這將「添加此功能的標準」:) –