如何将动态变量用作数组元素。

huangapple go评论48阅读模式
英文:

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.

huangapple
  • 本文由 发表于 2023年5月11日 08:18:03
  • 转载请务必保留本文链接:https://go.coder-hub.com/76223348.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定