Re-implementing lists with closures in scheme

ぐ巨炮叔叔 提交于 2019-12-08 07:06:29

问题


This is purely a curiosity question for me:

So for fun, one can easily redefine cons, car, and cdr like so:

(define cons+
  (lambda (a b)
    (lambda (f)
      (f a b)
  )))

(define car+
  (lambda (f)
    (f (lambda (a b) a))))

(define cdr+
  (lambda (f)
    (f (lambda (a b) b))))

This creates the basic functionality of a list using closures. In this context, what would be the best way to define an empty list?


回答1:


There's no particular special value that you need as the empty list; you just need something and then to treat it as the empty list. In Common Lisp, a list is either a cons or the symbol NIL. You could take the same approach and use the symbol NIL, or you could use some other value, so long as you treat it consistently. Part of the beauty (and sometimes, the ugliness) of linked lists in the Lisp families is that they are intensional data structures. They're built out of a bit of structure and a lot of convention. That's why we can use cons cells to implement singly-linked lists, tree, etc.

Now, what does it mean to treat it consistently? Some of that will depend on exactly how you want it to behave. In Common Lisp, you can call car and cdr with the empty list, and you'll get back the empty list. In Scheme, you'll get an error. In the closure-based approach, you've got a "leaky" abstraction in the sense that you can call car+ and cdr+ with values that were not produced by cons+, and you might get a value back.

What interface do you want?

When implementing singly linked lists in the Lisp styles (conses and an empty list), you typically want an interface that will let you check:

(cons? (cons ...)) == true
(empty? empty)     == true

(In terms of those, you can implement list?)

(define (list? x)
  (or (cons? x)
      (null? x)))

After what you've already done, it shouldn't be hard to implement a cons? function. But what about empty?? You actually have a lot of freedom here. You could implement empty? such that there are actually multiple objects that serve as a empty lists. As long as the contract works, it's OK.

Should anything else work?

At the moment, you've got a working implementation of ordered pairs, but it's a leaky abstraction in that some things that weren't created with cons could still be passed to car and cdr without any error. You've satisfied the axioms

(car (cons x y)) == x
(cdr (cons x y)) == y

but not the implications

(car z) == x     ⇒     z == (cons x _)
(cdr z) == y     ⇒     z == (cons _ y)

If you can find a way to make those implications true, so that car and cdr only work with things produced by cons, then you can probably figure out how to implement cons?, and you can use the same technique to generate a unique empty list object.



来源:https://stackoverflow.com/questions/27111724/re-implementing-lists-with-closures-in-scheme

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!