英文:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论