Common lisp 使用“声明全局变量”;人工的;象征
所谓“人工”,我指的是使用Common lisp 使用“声明全局变量”;人工的;象征,common-lisp,Common Lisp,所谓“人工”,我指的是使用intern或makesymbol从字符串创建的符号 我的代码中有一部分声明了多达49个全局变量: (defparameter *CHAR-COUNT-1-1* (make-hash-table)) ... (defparameter *CHAR-COUNT-1-7* (make-hash-table)) ... (defparameter *CHAR-COUNT-7-7* (make-hash-table)) 我想,相反,我可以创建一个函数来完成这一切: (loop
intern
或makesymbol
从字符串创建的符号
我的代码中有一部分声明了多达49个全局变量:
(defparameter *CHAR-COUNT-1-1* (make-hash-table))
...
(defparameter *CHAR-COUNT-1-7* (make-hash-table))
...
(defparameter *CHAR-COUNT-7-7* (make-hash-table))
我想,相反,我可以创建一个函数来完成这一切:
(loop for n from 1 to 7 do
(loop for i from 1 to 7 do
(defparameter (symbol-value (intern (concatenate 'string "*CHAR-COUNT-" (write-to-string n) "-" (write-to-string i) "*")))
(make-hash-table :test 'equalp))))
但是得到错误(sbcl):
线程中未处理的简单错误#:
无法将非符号声明为特殊:(symbol-VALUE)
(实习生)
(连接“字符串”*字符计数-
(写入字符串N)“-”
(写入字符串I)
"*")))
正确的方法是什么?使用带有
DEFPARAMETER
stanzas的PROGN
宏或“使用,它是一个函数,而不是宏”。DEFPARAMETER是一个宏,而不是一个函数。这意味着它定义了一种特殊的语法。defparameter表单需要有一个符号作为其第二个参数,但您提供了以下列表:
(symbol-value (intern (concatenate 'string "*CHAR-COUNT-" (write-to-string n) "-" (write-to-string i) "*")))
你想要的是一个像
您似乎对循环和创建符号以创建该列表非常熟悉;换衣服
(loop … do (loop … do (defparameter …)))
到
你可以得到你需要的表格。然后,只需将其全部放入宏中即可
(defmacro … (…)
`(progn
,@(loop … nconcing
(loop … collecting
`(defparameter ,(intern …) …)))))
和调用宏。正确的方法是使用正确的数据结构,而不是用符号名对维度进行编码。您真的想在任何时候访问正确的表时计算和编码符号名称吗
(defparameter *char-counts* (make-array '(7 7)))
(dotimes (i 49) ; or (reduce #'* (array-dimensions *char-counts*))
(setf (row-major-aref *char-counts* i) (make-hash-table)))
现在,您只需使用索引即可访问表数组(x
和y
,在本例中):
将维度信息嵌入变量名似乎应该是不同的数据结构,如二维数组。但如果你真的想这么做,一个简单的方法是通过macrolet;您不需要符号的值……您还需要宏扩展def参数。
`(progn
,@(loop … nconcing
(loop … collecting
`(defparameter ,(intern …) …))))
(defmacro … (…)
`(progn
,@(loop … nconcing
(loop … collecting
`(defparameter ,(intern …) …)))))
(defparameter *char-counts* (make-array '(7 7)))
(dotimes (i 49) ; or (reduce #'* (array-dimensions *char-counts*))
(setf (row-major-aref *char-counts* i) (make-hash-table)))
(gethash (aref *char-counts* x y) :foo)