我想使用其中一个参数动态创建一个带有defmethod
或defun
的哈希表来创建名称。例如:
(defun foo (arg)
(let ((NAME (read-from-string (format nil "\*~S\*" arg))))
(defparameter NAME (make-hash-table))))
当然,foo
使用符号NAME
创建哈希表,而不是NAME
中let
的值。如何获取NAME
的值来创建此哈希表?
答案 0 :(得分:7)
在函数中创建全局变量几乎总是错误的。
使用read-from-string
代替intern
创建新符号几乎总是错误的。
你可能想要的是
(defmacro def-ht (name)
(let ((var (intern (concatenate 'string "*" (symbol-name name) "*")
(symbol-package name))))
`(defparameter ,var (make-hash-table))))
(def-ht foo)
您也可以在函数中执行此操作 - 检查macroexpansion表单的defparameter
并将所需内容放入函数中:
(defun make-ht-var (name)
(let ((var (intern (concatenate 'string "*" (symbol-name name) "*")
(symbol-package name))))
(setf (symbol-value var) (make-hash-table))
(proclaim (list var 'special))))
(make-ht-var 'foo)
请注意函数的参数是引用,但宏的参数是而不是。
答案 1 :(得分:-1)
您需要使用宏而不是函数。 DEFPARAMETER会将MAKE-HASH-TABLE的值绑定到符号NAME,因为它会在比运行时更早的宏扩展时间内进行计算,这是函数FOO绑定NAME的词汇值时。
查看CL评估模型以获得更深入的理解。
(defmacro foo (arg)
(let ((name (read-from-string (format nil "*~S*" arg))))
`(defparameter ,name (make-hash-table))))
(foo "my-hash")
=> <hash-table 0x121>
*my-hash*
=> <hash-table 0x121>