Lisp 使用在运行时确定名称的defparameter定义变量

Lisp 使用在运行时确定名称的defparameter定义变量,lisp,common-lisp,Lisp,Common Lisp,我想用defmethod或defun使用其中一个参数来创建名称,从而动态启动一个哈希表。例如: (defun foo (arg) (let ((NAME (read-from-string (format nil "\*~S\*" arg)))) (defparameter NAME (make-hash-table)))) 当然,foo使用符号NAME创建哈希表,而不是let中NAME的值。如何获取NAME的值来创建此哈希表?您需要使用宏而不是函数。DEFPARAMETER将MA

我想用
defmethod
defun
使用其中一个参数来创建名称,从而动态启动一个哈希表。例如:

(defun foo (arg)
  (let ((NAME (read-from-string (format nil "\*~S\*" arg))))
    (defparameter NAME (make-hash-table))))

当然,
foo
使用符号
NAME
创建哈希表,而不是
let
NAME
的值。如何获取
NAME
的值来创建此哈希表?

您需要使用宏而不是函数。DEFPARAMETER将MAKE-HASH-TABLE的值绑定到符号名,因为它在宏扩展时求值,该时间早于运行时,即函数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>
(defmacro foo(arg)
(let((名称(从字符串读取(格式为nil”*~S*“arg)))
`(defparameter,名称(生成哈希表)))
(foo“我的哈希”)
=> 
*我的杂烩*
=> 

您需要使用宏而不是函数。DEFPARAMETER将MAKE-HASH-TABLE的值绑定到符号名,因为它在宏扩展时求值,该时间早于运行时,即函数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>
(defmacro foo(arg)
(let((名称(从字符串读取(格式为nil”*~S*“arg)))
`(defparameter,名称(生成哈希表)))
(foo“我的哈希”)
=> 
*我的杂烩*
=> 
一般说明
  • 在函数中创建全局变量几乎总是错误的

  • 几乎总是错误的使用而不是使用新符号来创建新符号

使用宏 你可能想要的是

(defmacro def-ht (name)
  (let ((var (intern (concatenate 'string "*" (symbol-name name) "*")
                     (symbol-package name))))
    `(defparameter ,var (make-hash-table))))
(def-ht foo)
使用函数 您也可以在函数中执行此操作-通过检查表单的格式并在函数中放置所需的内容:

(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)
请注意,函数的参数已被引用,但宏的参数未被引用。

一般说明
  • 在函数中创建全局变量几乎总是错误的

  • 几乎总是错误的使用而不是使用新符号来创建新符号

使用宏 你可能想要的是

(defmacro def-ht (name)
  (let ((var (intern (concatenate 'string "*" (symbol-name name) "*")
                     (symbol-package name))))
    `(defparameter ,var (make-hash-table))))
(def-ht foo)
使用函数 您也可以在函数中执行此操作-通过检查表单的格式并在函数中放置所需的内容:

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

请注意,函数的参数是带引号的,但宏的参数不是带引号的。

defmacro defht自己完成任务。但是,现在我想在defmethod中使用这个函数:
(defmethod init:after((self myclass))(deft self))
,在这种情况下,我得到一个名为*self*的哈希表,而不是self name。当然,这是因为宏不计算其参数。您需要使用函数版本。defmacro defht自己完成这项工作。但是,现在我想在defmethod中使用这个函数:
(defmethod init:after((self myclass))(deft self))
,在这种情况下,我得到一个名为*self*的哈希表,而不是self name。当然,这是因为宏不计算其参数。您需要使用函数版本。这可能不是OP想要的,因为如果OP这样做,例如,
(defun bar(x)(foo x))
,OP将得到一个名为
*x*
的哈希表,即使在这样做时,例如<代码>(在“我的哈希”栏上)。明白了<代码>(defmethod init((self myclass))(eval(列出“defparameter(从字符串读取)(格式为nil”*~S*“self)))(生成哈希表)))。。。thanks@JoshuaTaylor,你完全正确。我的版本只在顶层工作。这可能不是OP想要的,因为如果OP这样做,例如,
(defun bar(x)(foo x))
,OP将得到一个名为
*x*
的哈希表,即使在这样做时,例如<代码>(在“我的哈希”栏上)。明白了<代码>(defmethod init((self myclass))(eval(列出“defparameter(从字符串读取)(格式为nil”*~S*“self)))(生成哈希表)))。。。thanks@JoshuaTaylor,你完全正确。我的版本只在顶层工作。