DeathKing
DeathKing

Reputation: 173

How to make a copy of a procedure in Scheme?

So, from the SICP we know that the cons car and cdr can be defined as a procedure:

(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)))

But the pre-defined procedure list, which takes the arguments to build a list, uses the original cons. That means, a list that list built, isn't a procedure as I want.

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

So i write this:

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

I just wondering how to define the original-car and original-cdr. Are there some way to make a copy of a procedure in Scheme? Or there's some alternate way to solve this problem. thx

Upvotes: 1

Views: 711

Answers (2)

Sylwester
Sylwester

Reputation: 48765

List in an implementation is defined as

(define (list . l) l)

However, this is using a lot of the underlying implementation. E.g. to work it uses the native cons. cons as defined in SICP is a thought experiment so you're implementation needs a little correction:

(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 and my-list are as defined in your question. Only change is reference to correct procedure (with name not conflicting with Scheme)

Upvotes: 2

Óscar López
Óscar López

Reputation: 236112

If you need to save a reference to the "original" procedures before redefining them, simply create an alias before defining the "new" procedures (I guess that's what you mean by "copying" them). Like this:

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

In this way, the old procedures can still be used, as long as we refer to them by their new names. In other words, the implementation of cons, car, cdr and list as procedures will look like this:

(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)))))

And sure enough, it works:

(define lst (my-list 1 2 3 4))
lst
=> #<procedure>
(my-car lst)
=> 1
(my-car (my-cdr lst))
=> 2

Upvotes: 4

Related Questions