如何在Scheme中复制程序?

时间:2013-06-09 02:03:43

标签: list scheme

因此,从 SICP ,我们知道cons carcdr可以定义为一个过程:

(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-caroriginal-cdr。有没有办法在Scheme中复制一个过程?或者有一些替​​代方法来解决这个问题。 THX

2 个答案:

答案 0 :(得分:4)

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

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

通过这种方式,只要我们用新名称引用旧程序,它们仍然可以使用。换句话说,conscarcdrlist作为程序的实现将如下所示:

(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

答案 1 :(得分: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是你问题中定义的。只有更改才能引用正确的程序(名称与Scheme不冲突)