在Clojure中,不能在库级别有效地实现单元格吗?

时间:2018-04-23 14:26:34

标签: data-structures clojure lisp cons

Clojure有自己的系列,不需要传统的lispy cons细胞。但我觉得这个概念很有意思,并且它被用在一些教学材料中(例如,SICP)。我一直想知道这个cons原语是否需要是原始的。我们不能在库中实现它(以及在其上运行的传统函数)吗?我搜索过,但是我发现还没有写过这样的图书馆。

3 个答案:

答案 0 :(得分:5)

Cons单元格是Lisp中用于s表达式的重要构建块。例如,参见麦卡锡关于Lisp的各种出版物和1958年以后的符号表达式(例如Recursive Functions of Symbolic Expressions)。 Lisp中的每个列表都由cons单元组成。

使用cons单元作为库来实现链表(和树,......)绝对是可能的。但是对于Lisp来说,它们是如此重要,以至于它很早就需要它们并且实现非常有效。

在Lisp系统中,通常有许多缺点单元和分配新缺陷单元的高速率(称为 consing )。因此,Lisp的实现者可能希望优化其Lisp实现:

  • 小尺寸的cons细胞 - >不超过两个机器字,一个字为汽车,一个字为 cdr
  • 快速分配新的利弊细胞
  • cons细胞的有效垃圾收集(不再使用cons细胞很快找到)
  • 直接在cons单元格中存储原始数据(数字,字符......) - >没有指针开销
  • 优化Lisp数据的局部性,例如cons单元结构(列表,关联列表,树,......),例如通过使用生成/复制垃圾收集器和/或用于cons单元的内存区域

因此,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细胞根本就没有很大的需求。结合以下事实,即确实的任何人都希望他们重新实施起来非常容易,并且没有潜在的图书馆解决方案客户。