2012-05-22 26 views
5

Tôi đang tìm một cách có thể không tiết kiệm để khởi tạo bảng băm trong Common Lisp. Ví dụ. một cái gì đó mà làm việc cho các bảng băm liên tục, mà còn để tải trước các băm biến. Trong CLISP tôi đang sử dụng:Common Lisp: viết tắt để khởi tạo một bảng băm với nhiều mục nhập

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

nhưng tiếc là định dạng này chỉ hoạt động trên CLISP.

+0

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

+0

Lưu ý rằng vd http://www.aiai.ed.ac.uk/~jeff/lisp/cl-pitfalls cảnh báo chống lại việc sử dụng các bảng băm làm giá trị cho các dạng 'defconstant'. – Hugh

+0

Xin cảm ơn tất cả. Có vẻ như tính năng cơ bản này thiếu tiêu chuẩn và phải được thêm vào theo một cách nào đó. Thay vì giới thiệu cú pháp mới, bắt chước Perl hoặc PHP, bạn nghĩ gì về việc viết macro bao bọc bảng băm và thêm tùy chọn: nội dung ban đầu, tùy chọn tương tự được hỗ trợ trong tiêu chuẩn bằng, ví dụ: make-array? Tôi nghĩ rằng điều này sẽ không có thể rất hiệu quả, vì nội dung sẽ được xác định bởi một alist mà phải được duyệt qua, nhưng ít nhất nó phù hợp hơn với cú pháp Lisp. –

Trả lời

6

Một lập trình có thể xây dựng một bảng băm lúc đọc:

(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*) 

#. được sử dụng để đánh giá thời gian đọc. Trình biên dịch sau đó sẽ đổ bảng băm vào tệp FASL.

này sau đó có thể được biên dịch:

Sử dụng 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}> 

Tạo một bảng băm là một hàm:

(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

Cảm ơn rất nhiều Reiner! Hạn chế duy nhất là đó là một chút tiết, nhưng điều đó có thể được trợ giúp bằng cách sử dụng một macro. Tôi là một người mới bắt đầu Lisp và không giỏi về macro. Dù sao, đây là của tôi: '(defmacro ini-hash-table (cặp) ' (let ((hash (make-hash-table: test 'bằng nhau))) (vòng lặp cho (giá trị khóa),, theo #' cddr do (setf (giá trị băm khóa gethash))) băm)) Sau đó tôi làm: '(defvar * ht * #. (ini-băm-bảng '(a 1 b 2 c 3)))' –

+1

@AntonioBonifati : khi tôi nghi ngờ viết một hàm, không phải macro. Không có lý do nó nên là vĩ mô, phải không? –

+1

Vâng, cảm ơn, tôi biết, một lý do chính đáng cho điều đó là các macro khó viết và gỡ lỗi hơn. Nhưng nếu tôi viết một hàm trong trường hợp này, tôi không thể gọi nó bằng #. Ít nhất trong ECL nó nói với tôi nó là không xác định. Tôi nghĩ đây là hiệu ứng của #. đó là bất kỳ hàm do người dùng định nghĩa nào không có sẵn ở thời gian đọc. Tôi tự hỏi nếu một wrapper macro có thể được viết cho phép một cấu hình đầy đủ make-hash-bảng trong khi thêm một: tham số từ khóa nội dung ban đầu. Điều đó sẽ "thêm tính năng này vào tiêu chuẩn" :) –

Các vấn đề liên quan