lisp - Common Lisp 中的值函数

标签 lisp common-lisp

Common Lisp 中的值函数只是语法糖,用于将多个值打包到一个列表中,该列表会被调用者解构吗?我问是因为我认为 Common Lisp 支持“真正的”多值返回,而不是像 python 等其他语言那样返回元组或列表。有人刚刚告诉我这只是语法糖,所以我希望有人好心解释一下。为了尝试理解 values 函数返回的类型,我输入了 (type-of (values 1 2 3)),输出为 BIT。我在 Common Lisp 引用资料中搜索了它,但在数据类型部分找不到它。另外,任何人都可以分享一些资源来建议如何在 Common Lisp 中实现值功能吗?。谢谢。

最佳答案

CL 中的多个值

语言 Common lisp 在 ANSI 标准 INCITS 226-1994 (R2004) 中进行了描述,并且有许多 实现。 每个都可以实现multiple values 在它认为合适的情况下,当然,他们可以为他们列一个 list (实际上,the Emacs Lisp compatibility layer for CL does just that - 但它是,强调和有意地,不是 Common Lisp 实现)。

目的

但是,此设施的目的是为了让通过(至少 一些)多个值 without cons (即,没有分配 heap内存)和所有CL 我知道的实现是这样做的。 从这个意义上说,多值设施是一种优化

当然,此功能的实现可能因人而异 不同的平台和场景。例如,前几个(例如 20 - required by the standard )是 存储在线程局部向量的静态中,接下来的几个(1000?)是 分配在堆栈上,其余的(如果需要)分配在 堆作为向量或列表。

用法

例如,函数 floor返回两个值。 如果你写

(setq a (floor 10 3))

你只捕获第一个并丢弃第二个,你需要 写

(setf (values q r) (floor 10 3))

捕获两个值。这类似于 other languages可能表示为

q,r = floor(10,3)

使用 tuples , 除了 CL 做 分配内存来传递(仅几个)多个值,并且 其他语言通常也是如此。

IOW,可以将多个值视为一个临时结构。

请注意,CL 可以将多个值转换为列表:

(destructuring-bind (q r) (multiple-value-list (floor 10 3))
  ; use q & r here
  ...)

而不是更高效简洁

(multiple-value-bind (q r) (floor 10 3)
  ; use q & r here
  ...)

MV & 类型

CL 没有“多值对象”的特殊类型 正是因为它没有分配一个单独的对象来传递 围绕多个值。从这个意义上说,我们确实可以声称 values是句法糖。

但是,在 CL 中可以 declare A function type返回 multiple values :

(declaim (ftype (real &optional real) (values real real)) floor)

这意味着 floor返回两个值,两者 real s(相对于返回 (values real real) 类型的值,即,在这种情况下,可能 声明滥用符号。

你的情况

在您的具体情况下,type-of 是普通函数(即不是宏或特殊运算符)。 您将单个对象 1 传递给它,因为除非您使用 multiple-value-bind和 friend ,只使用第一个值,所以

(type-of (values 1 2 3))

等同于

(type-of 1)

1 的类型是 bit .

PS: 控制返回值

一次使用values是为了 控制函数的返回值。 通常 CL 函数的返回值是最后一种形式的返回值。 有时这是不可取的,例如,最后一个表格返回多个 values 并且你希望你的函数返回一个值(或者没有, 喜欢voidC 中:

(defun 2values (x y)
  (floor y x))
(defun 1value (x y)
  (values (floor y x)))
(defun no-values (x)
  (print x)
  (values))

关于lisp - Common Lisp 中的值函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22795608/

相关文章:

C解析器递归

clojure - 在 clojure 中,如果定义为 [x] 参数然后引用为 x,为什么不识别 x?在代码块中?

lisp - 无法在 lisp 中将字符串/字符转换为字节

lisp - 如何在 lisp 中计算两次(不使用 eval)

loops - Common Lisp - 将函数应用于列表中的每个其他元素

LISP逐级显示二叉树

lisp - 普通口齿不清 : Function returns function name

sockets - 使用 CCL 发送 UDP 时出现问题

postgresql - 在 CL 后现代什么 :col-type to use for Many to Many field?

lisp - 传教士和食人者 - LISP