1

所以,从SICP我们知道cons carandcdr可以定义为一个过程:

(define (cons x y)
    (lambda (m) (m x y)))

(define (car z)
    (z (lambda (p q) p)))

(define (cdr z)
    (z (lambda (p q) q)))

但是预定义的过程list,它接受参数来构建一个列表,使用原始的cons. 这意味着,list构建的列表不是我想要的过程。

(car (list 1 2 3))
;The Object (1 2 3) is not applicable

所以我写这个:

(define (list . l)
    (if (null? l)
        '()
        (cons (original-car l)
              (list (original-cdr l)))))

我只是想知道如何定义original-carand original-cdr。有什么方法可以复制 Scheme 中的程序吗?或者有一些替​​代方法可以解决这个问题。谢谢

4

2 回答 2

4

如果您需要在重新定义它们之前保存对“原始”过程的引用,只需在定义“新”过程之前创建一个别名(我猜这就是您所说的“复制”它们的意思)。像这样:

(define original-cons cons)
(define original-car car)
(define original-cdr cdr)
(define original-list list)

这样,旧的程序仍然可以使用,只要我们用它们的新名称来引用它们。换句话说, 、 和 as 过程的实现conscar如下cdr所示list

(define (my-cons x y)
  (lambda (m) (m x y)))

(define (my-car z)
  (z (lambda (p q) p)))

(define (my-cdr z)
  (z (lambda (p q) q)))

(define (my-list . els)
  (if (null? els)
      '()
      (my-cons
       (original-car els)
       (apply my-list (original-cdr els)))))

果然,它有效:

(define lst (my-list 1 2 3 4))
lst
=> #<procedure>
(my-car lst)
=> 1
(my-car (my-cdr lst))
=> 2
于 2013-06-09T03:25:54.820 回答
2

实现中的列表定义为

(define (list . l) l)

但是,这使用了很多底层实现。例如,它使用原生的缺点来工作。cons如中所定义的SICP是一个思想实验,所以你的实现需要一些修正:

(define (my-cons x y)
    (lambda (m) (m x y)))

(define (my-car z)
    (z (lambda (p q) p)))

(define (my-cdr z)
    (z (lambda (p q) q)))

(define (my-list . l)
  (define (my-list-aux l)
    (if (null? l)
        '()
        (my-cons (car l)
                 (my-list-aux (cdr l)))))
  (my-list-aux l))

;; optional, update binding
(define car my-car)
(define cdr my-cdr)
(define list my-list)

my-cons my-car、my-cdr 和 my-list 如您的问题中所定义。唯一的变化是引用正确的程序(名称与方案不冲突)

于 2013-06-09T02:36:30.433 回答