user10853826
user10853826

Reputation: 11

car implementation in scheme

I am trying to write by myself the cons function in scheme. I have written this code:

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

and I am trying to run :

(car. '(1 2 3))

I expect to get the number 1, but it does not work properly.

Upvotes: 1

Views: 997

Answers (2)

Mulan
Mulan

Reputation: 135227

Sylwester's answer is great. Here's another possible implementation of null, null?, cons, car, cdr -

(define null 'null)

(define (null? xs)
  (eq? null xs))

(define (cons a b)
  (define (dispatch message)
    (match message
      ('car a)
      ('cdr b)
      (_ (error 'cons "unsupported message" message))
  dispatch)

(define (car xs)
  (if (null? xs)
      (error 'car "cannot call car on an empty pair")
      (xs 'car)))

(define (cdr xs)
  (if (null? xs)
      (error 'cdr "cannot call cdr on an empty pair")
      (xs 'cdr)))

It works like this -

(define xs (cons 'a (cons 'b (cons 'c null))))

(printf "~a -> ~a -> ~a\n"
        (car xs)
        (car (cdr xs))
        (car (cdr (cdr xs))))
;; a -> b -> c

It raises errors in these scenarios -

(cdr null)
; car: cannot call car on an empty pair

(cdr null)
; cdr: cannot call cdr on an empty pair

((cons 'a 'b) 'foo)
;; cons: unsupported dispatch: foo

define/match adds a little sugar, if you like sweet things -

(define (cons a b)
  (define/match (dispatch msg)
    (('car) a)
    (('cdr) b)
    (('pair?) #t)
    ((_) (error 'cons "unsupported dispatch: ~a" msg)))
  dispatch)

((cons 1 2) 'car)   ;; 1
((cons 1 2) 'cdr)   ;; 2
((cons 1 2) 'pair?) ;; #t
((cons 1 2) 'foo)   ;; cons: unsupported dispatch: foo

Upvotes: 1

Sylwester
Sylwester

Reputation: 48745

When you implement language data structures you need to supply constructors and accessors that conform to the contract:

(car (cons 1 2))   ; ==> 1
(cdr (cons 1 2))   ; ==> 2
(pair? (cons 1 2)) ; ==> 2

Here is an example:

(define (cons a d)
  (vector a d))
(define (car p)
  (vector-ref p 0))
(define (cdr p)
  (vector-ref p 1))

Now if you make an implementation you would implement read to be conformant to this way of doing pairs so that '(1 2 3) would create the correct data structure the simple rules above is still the same.

From looking at car I imagine cons looks like this:

(define (cons a d)
  (lambda (p) (p a d)))

It works with closures. Now A stack machine implementation of Scheme would analyze the code for free variables living passed their scope and thus create them as boxes. Closures containing a, and d aren't much different than vectors.

I urge you to implement a minimalistic Scheme interpreter. First in Scheme since you can use the host language, then a different than a lisp language. You can even do it in an esoteric language, but it is very time consuming.

Upvotes: 1

Related Questions