gpt4 book ai didi

reference - 在Common Lisp中,什么时候引用对象,什么时候直接按值访问?

转载 作者:太空宇宙 更新时间:2023-11-03 18:51:30 25 4
gpt4 key购买 nike

我正在阅读 this question尝试深入了解答案。它专门询问传递引用,所有答案似乎都表明不支持传递引用。然而,this answer这意味着,虽然可能不支持通过引用传递,但某些值确实可以通过引用访问。一个更简单的例子是 cons cells;我可以将一个 cons 单元格传递给一个函数,然后将它的 cdr 或 car 更改为我喜欢的任何内容。

最后,我想知道(用 C# 的说法)值类型和引用类型之间是否有明确的区分,以及是否有任何方法(比上面引用的答案更方便)将值视为引用类型。

最佳答案

没有区别:所有对象在 Lisp 中都是按值传递的(至少在我所知道的所有 Lisp 中)。 但是一些对象是可变的,conses 就是这样一种类型。所以你可以将一个 cons cell 传递给一个过程并在该过程中改变它。因此,重要的考虑因素是对象是否可变。

特别是这个 (Common Lisp) 函数总是返回 T 作为它的第一个值,即使它的第二个值可能没有 0 作为它的汽车或 cdr。

(defun cbv (&optional (f #'identity))
(let ((c (cons 0 0)))
(let ((cc c))
(funcall f c)
(values (eq c cc) c))))

> (cbv (lambda (c)
(setf (car c) 1
(cdr c) 2)))
t
(1 . 2)

然而,由于 Common Lisp 具有词法作用域、一流的函数和宏,您可以做一些技巧,使它看起来有点像正在发生按引用调用:

(defmacro capture-binding (var)
;; Construct an object which captures a binding
`(lambda (&optional (new-val nil new-val-p))
(when new-val-p
(setf ,var new-val))
,var))

(defun captured-binding-value (cb)
;; value of a captured binding
(funcall cb))

(defun (setf captured-binding-value) (new cb)
;; change the value of a captured binding
(funcall cb new))

(defun cbd (&optional (f #'identity))
(let ((c (cons 0 0)))
(let ((cc c))
(funcall f (capture-binding c))
(values (eq c cc) c cc))))

现在:

> (cbd (lambda (b)
(setf (captured-binding-value b) 3)))
nil
3
(0 . 0)

如果您了解它是如何工作的,那么您可能会非常了解作用域和宏在 Lisp 中的工作方式。


在 Common Lisp 中按值传递对象的普遍性有一个异常(exception),Rainer 在下面的评论中提到了这一点:某些原始类型的实例可能会在某些情况下被复制以提高效率。这只会发生在特定类型的实例上,并且它发生的对象总是不可变的。为了处理这种情况,CL 提供了一个等式谓词 eql这与 eq 做同样的事情, 除了它知道可能以这种方式 secret 复制的对象并正确地比较它们。

所以,安全的做法是使用 eql 而不是 eq:因为可以复制的对象总是不可变的,这意味着你永远不会被这个。

这是一个示例,其中您自然认为相同的对象结果却不同。给定这个定义:

(defun compare (a b)
(values (eq a b)
(eql a b)))

然后在我使用的实现中我发现:

> (compare 1.0d0 1.0d0)
nil
t

所以 double 浮点零不是 eq 对它自己,总是,但它总是 eql 对它自己。并尝试一些看起来应该相同的东西:

> (let ((x 1.0d0)) (compare x x))
t
t

所以在这种情况下,看起来函数调用不是复制对象,而是我从读取器中的两个不同对象开始。然而,始终允许实现随意​​复制数字,并且很可能会使用不同的优化设置。

关于reference - 在Common Lisp中,什么时候引用对象,什么时候直接按值访问?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54018077/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com