英文:
How to use dynamic variables as elements of an array
问题
(defparameter *foo* '(1 2 3))
(defparameter *bar* '(3 4 5))
(defparameter *baz*
  (list *foo* *bar*))
(elt (nth 0 *baz*) 1)
英文:
I would like to use an array or list to store dynamic variables for later retrieval via an index. So if I have:
(defparameter *foo* '(1 2 3))
(defparameter *bar* '(3 4 5))
(defparameter *baz*
  (make-array 2 :initial-contents '(*foo* *bar*)))
I would like to retrieve *foo* by calling (aref *baz* 0) and have this return '(1 2 3)
Of course, this doesn't work and the *foo* stored in *baz* isn't even the special variable I defined at top-level, as shown when I try to do (elt (aref *baz* 0) 1) which only returns an error and not the value 2. Let me say I am new to Common Lisp and I don't even know how to describe this question in a way that helped me in searching through CLHS, etc. Any help would be appreciated!
答案1
得分: 3
你需要理解符号(在Lisp中是一种数据类型)与其值之间的区别。符号作为一个对象存在,符号的值要么是评估的结果,要么可以通过访问符号值来检索。Lisp是少数几种语言之一,其中符号是一种一流的数据类型,并且具有可以设置和绑定的值。
> '*foo*
*foo*       ; 符号*foo*本身
> *foo*
(1 2 3)     ; 符号*foo*的值 -> 这个列表
> (eval '*foo*)
(1 2 3)     ; 符号*foo*的值 -> 这个列表
> (symbol-value '*foo*)
(1 2 3)     ; 符号*foo*的值 -> 这个列表
可以使用函数symbol-value检索符号的值:
(symbol-value '*foo*)
(let ((symbol '*foo*))
  (symbol-value symbol))
英文:
You need to understand the difference between a symbol (which is a data type in Lisp) and its value. The symbol exists as an object. The value of a symbol is either the result of an evaluation or can be retrieved by accessing the symbol value. Lisp is one of the few languages where a symbol is a first class datatype and which has also a value which can be set and bound.
> '*foo*
*foo*       ; the symbol *foo* itself
> *foo*
(1 2 3)     ; the value of the symbol *foo* -> this list
> (eval '*foo*)
(1 2 3)     ; the value of the symbol *foo* -> this list
> (symbol-value '*foo*)
(1 2 3)     ; the value of the symbol *foo* -> this list
One can retrieve the value of a symbol with the function symbol-value:
(symbol-value '*foo*)
(let ((symbol '*foo*))
  (symbol-value symbol))
答案2
得分: 2
我建议你阅读 《何时在Lisp中使用'(或引号)》 和 CLHS 的 quote条目,以获得全面的解释。
我只会关注你代码中的两个问题:
引用的使用
看看 '(*foo* *bar*)。 quote 阻止对这两个符号的评估,因此该表达式的结果将是一个包含两个符号 *foo* 和 *bar* 的列表。
与 (list *foo* *bar*) 进行比较 - 在评估过程中,符号 *foo* 和 *bar* 被评估为它们的值,所以结果将是 '((1 2 3) (3 4 5))。
引用列表的使用
正如 CLHS quote 条目 所述:
> 如果对文字对象(包括引用的对象)进行破坏性修改,则后果是未定义的。
如果你想稍后修改你的列表,你应该用 list 或另一个函数创建它们。
因此,你的代码应该像这样:
(defparameter *foo* (list 1 2 3))
(defparameter *bar* (list 3 4 5))
(defparameter *baz*
  (make-array 2 :initial-contents (list *foo* *bar*)))
我也会考虑使用二维数组,这样你可以将 elt + aref 结合成一个 (aref *baz* 0 0),但这取决于你要解决的确切问题。
英文:
I suggest you to read When to use ' (or quote) in Lisp? and CLHS quote entry for a comprehensive explanation.
I will just focus on two problems in your code:
Usage of quote
Look at '(*foo* *bar*). quote stops the evaluation of these two symbols, so result of this expression will be a list with two symbols, *foo* and *bar*.
Compare that with (list *foo* *bar*)- during evaluation, symbols *foo* and *bar* are evaluated to their values, so the result will be '((1 2 3) (3 4 5)).
Usage of quoted lists
As CLHS quote entry says:
> The consequences are undefined if literal objects (including quoted
> objects) are destructively modified.
If you want to modify your lists later, you should create them with list or another function.
So, your code should look like this:
(defparameter *foo* (list 1 2 3))
(defparameter *bar* (list 3 4 5))
(defparameter *baz*
  (make-array 2 :initial-contents (list *foo* *bar*)))
I would also consider using 2d array, so you can combine elt + aref into one (aref *baz* 0 0), but that depends on the exact problem you're trying to solve.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论