Clojure有自己的系列,不需要传统的lispy cons细胞。但我觉得这个概念很有意思,并且它被用在一些教学材料中(例如,SICP)。我一直想知道这个cons原语是否需要是原始的。我们不能在库中实现它(以及在其上运行的传统函数)吗?我搜索过,但是我发现还没有写过这样的图书馆。
答案 0 :(得分:5)
Cons单元格是Lisp中用于s表达式的重要构建块。例如,参见麦卡锡关于Lisp的各种出版物和1958年以后的符号表达式(例如Recursive Functions of Symbolic Expressions)。 Lisp中的每个列表都由cons单元组成。
使用cons单元作为库来实现链表(和树,......)绝对是可能的。但是对于Lisp来说,它们是如此重要,以至于它很早就需要它们并且实现非常有效。
在Lisp系统中,通常有许多缺点单元和分配新缺陷单元的高速率(称为 consing )。因此,Lisp的实现者可能希望优化其Lisp实现:
因此,Lisp系统使用各种技巧来实现这一目标。例如,指针可以编码,如果它们指向cons单元格 - 因此cons单元本身不需要类型标记。 Fixnums具有非常少的标记位并且适合cons细胞的CAR或CDR。在MIT Lisp机器上,当系统是线性列表的一部分时,系统还具有省略cons单元的CDR部分的功能。
为了实现所有这些优化目标,通常需要在汇编程序和/或C中手动调整Lisp运行时的实现.Lisp处理器或Lisp VM通常会提供CAR,CDR,CONS,CONSP,......机器说明。
就像TFB所说的那样:同样可以在库中实现浮点数,但与CPU支持的本机浮点数和运算相比,效率不高。 Lisp实现提供了非常低级别的缺陷单元。
但是在这样的Lisp实现之外,它显然可以将cons单元实现为库 - 具有更差的空间和时间效率。
旁注
Maclisp有超过两个名为Hunks
的插槽的缺陷单元格答案 1 :(得分:4)
您可以自己实施。这是一次尝试:
(defprotocol cons-cell
(car [this])
(cdr [this])
(rplaca [this v])
(rplacd [this v]))
(deftype Cons [^:volatile-mutable car
^:volatile-mutable cdr]
cons-cell
(car [this] (.car this))
(cdr [this] (.cdr this))
(rplaca [this value] (set! car value))
(rplacd [this value] (set! cdr value)))
(defn cons [car cdr]
(Cons. car cdr))
循环清单:
(let [head (cons 0 nil)]
(rplacd head head)
head)
答案 2 :(得分:0)
当然,您可以使用/* jshint esnext:true */
function myFunction() {
navigator.bluetooth.requestDevice({ filters: [{ services: ['heart_rate'] }] })
.then(device => { /* ... */ })
.catch(error => { console.log(error); });
}
(在Clojure中称为lambda
)以外的任何工具来实现cons单元。
fn
这与Clojure中的空间一样有效(在两个绑定上封闭的lambda只是一个具有两个字段的对象)。如果您使用记录或其他方法,(defn cons' [a d]
(fn [f] (f a d)))
(defn car' [c]
(c (fn [a d] a)))
(defn cdr' [c]
(c (fn [a d] d)))
user> (car' (cdr' (cons' 1 (cons' 2 nil))))
2
和car
显然可以节省更多时间;我要说的是,是的,即使您几乎没有可用的工具,您当然也可以制作缺点单元格。
为什么没有完成?我们已经有了更好的工具。 Clojure的序列抽象比cons细胞具有更好的列表,向量是一个非常好的元组。 cons细胞根本就没有很大的需求。结合以下事实,即确实的任何人都希望他们重新实施起来非常容易,并且没有潜在的图书馆解决方案客户。