Things to know when pro­gram­ming with Scheme

Created: Mon Nov 26 13:00:26 CET 2018

Last mod­i­fied: Tue Nov 27 16:26:06 CET 2018

I some­times add new con­tent at the top of the post.


(define (f x)
  (if (zero? x)
      (f (- x 1))))

(trace f)
(f 5)
(trace-let f ((x 5))
  (if (zero? x)
      (f (- x 1))))

We get the same out­put from both ex­am­ples:

|(f 5)
|(f 4)
|(f 3)
|(f 2)
|(f 1)
|(f 0)

Indicating that our func­tion f is tail-re­cur­sive. (There are no stacked | here.)

Consider the fol­low­ing code from TSPL3:

(define (make-queue)
  (let ((end (cons 'ignored '())))
    (cons end end)))

(define (putq! q v)
  (let ((end (cons 'ignored '())))
    (set-car! (cdr q) v)
    (set-cdr! (cdr q) end)
    (set-cdr! q end)))

(define (getq q)
  (caar q))

(define (delq! q)
  (set-car! q (cdar q)))

(define (emptyq? q)
  (null? (cdar q)))

We use cons in­stead of quote in the let-bindings. Two pairs cre­ated by the same call to cons are point­ers to the same pair. A mod­i­fi­ca­tion of one is a mod­i­fi­ca­tion of the other; thus al­low­ing us to keep a pointer to the end of the queue and add stuff there with­out walk­ing the en­tire queue. This would not be pos­si­ble were we to re­place (cons 'ignored '()) with '(ignored).

source code