相关疑难解决方法(0)

在common-lisp中,如何在不更改原始列表的情况下从函数内修改list参数的一部分?

我正在尝试将列表传递给Lisp中的函数,并在函数内更改该列表的内容,而不会影响原始列表.我已经读过Lisp是按值传递的,这是真的,但还有其他事情我不太明白.例如,此代码按预期工作:

(defun test ()
    (setf original '(a b c))
    (modify original)
    (print original))
(defun modify (n)
    (setf n '(x y z))
    n)
Run Code Online (Sandbox Code Playgroud)

如果你调用(测试),即使(修改)返回(xyz),它也会打印(abc).

但是,如果您尝试仅更改列表的一部分,则无法正常工作.我认为这与列表中的内容在内存中相同或者类似的内容有关?这是一个例子:

(defun test ()
    (setf original '(a b c))
    (modify original)
    (print original))
(defun modify (n)
    (setf (first n) 'x)
    n)
Run Code Online (Sandbox Code Playgroud)

然后(测试)打印(xbc).那么如何更改函数中list参数的某些元素,就好像该列表是该函数的本地列表一样?

lisp function common-lisp parameter-passing pass-by-reference

6
推荐指数
3
解决办法
6159
查看次数

试图理解setf + aref"魔法"

我现在已经了解了数组和arefLisp.到目前为止,它很容易掌握,它就像一个魅力:

(defparameter *foo* (make-array 5))
(aref *foo* 0) ; => nil
(setf (aref *foo* 0) 23)
(aref *foo* 0) ; => 23
Run Code Online (Sandbox Code Playgroud)

令我百思不解的是aref"神奇"当你把这种情况发生arefsetf.似乎aref知道它的调用上下文,然后决定是否返回一个值或一个可以使用的地方setf.

无论如何,目前我只是认为这是理所当然的,并且不要考虑内部工作方式太多.

但是现在我想创建一个将*foo*数组元素设置为预定义值的函数,但是我不想对*foo*数组进行硬编码,而是想要移交一个地方:

(defun set-23 (place)
  …)
Run Code Online (Sandbox Code Playgroud)

所以基本上这个函数集放置到23,任何地方.我最初的天真的方法是

(defun set-23 (place)
  (setf place 23))
Run Code Online (Sandbox Code Playgroud)

并使用以下方式调用:

(set-23 (aref *foo* 0))
Run Code Online (Sandbox Code Playgroud)

这不会导致错误,但也不会发生任何变化*foo*.我的猜测是aref解析的调用nil(因为数组当前是空的),所以这意味着

(setf nil 23)
Run Code Online (Sandbox Code Playgroud)

运行,但是当我在REPL中手动尝试时,我收到一个错误告诉我:

NIL是常量,不能用作变量

(这绝对有道理!)

所以,最后我有两个问题:

  1. 我的样本中发生了什么,这不会导致错误,为什么它不做任何事情?
  2. 我怎么能解决这个问题才能让我的set-23功能发挥作用?

我也有想法使用thunk来推迟执行aref,就像: …

lisp common-lisp

5
推荐指数
2
解决办法
738
查看次数

Common Lisp中的指针

我想将引用(指针)保存到我保存在另一个变量中的某些数据的一部分:

(let ((a (list 1 2 3)))
  (let ((b (car (cdr a)))) ;here I want to set b to 2, but it is set to a copy of 2
    (setf b 4))
  a) ;evaluates to (1 2 3) instead of (1 4 2)
Run Code Online (Sandbox Code Playgroud)

我可以使用宏,但如果我想在列表中间更改一些数据并且我不是很灵活,那么将会有很多代码要执行:

(defparameter *list* (create-some-list-of-arrays))
(macrolet ((a () '(nth 1000 *list*)))
  (macrolet ((b () `(aref 100 ,(a))))
    ;; I would like to change the macro a here if it were possible
    ;; but then b would mean something …
Run Code Online (Sandbox Code Playgroud)

lisp pointers common-lisp

2
推荐指数
1
解决办法
3310
查看次数

Common Lisp,对值和实际值的引用

考虑一下这段代码:

(defvar lst '(1 1))

(defmacro get-x (x lst)
  `(nth ,x ,lst))

(defun get-y (y lst)
  (nth y lst))
Run Code Online (Sandbox Code Playgroud)

现在让我们假设我想要更改名为lst的列表元素的值,使用get-xcar和使用get-ycdr.当我尝试用get-x(使用setf)更改值时,一切都很顺利但是如果我用get-y尝试它发出错误信号(缩短):

; 陷入STYLE-WARNING:; 未定义的功能:(SETF GET-STUFF)

为什么会这样?

我自己也怀疑,这是因为宏只是展开和函数第n简单地返回到列表中,并在另一方面,功能元素的值的参考评估函数调用到第n和返回参考价值的价值(听起来令人困惑).

我的怀疑是否正确?如果我是正确的,那么如何知道什么只是对价值和实际价值的引用?

macros reference common-lisp

1
推荐指数
1
解决办法
440
查看次数