Stumbled upon this curious syntax in a talk by Sussman:
(define ((f x) y) ...)
In standard Scheme:
(define (name . args) . body)
means:
(define name (lambda args . body))
In the past, I’ve implemented (define name . body)
syntax in a few evaluators as:
// Pseudo-C eval(env, expr) { ... if ( car(expr) == s_define ) { name = cadr(expr); body = cddr(expr); if ( pairQ(name) ) { return define(env, car(name), lambda(env, cdr(name), body)); } else { return define(env, name, car(body)); } } ... }
I was so wrong… the expansion of define
should recur if name is a pair:
eval(env, expr) { again: ... if ( car(expr) == s_define ) { name = cadr(expr); body = cddr(expr); if ( pairQ(name) ) { expr = list(s_define, car(name), cons(s_lambda, cons(cdr(name), body))); goto again; } else { return define(env, name, cadr(body)); } } ... }
Example:
(define (((sequence op) start constant) . rest) (let ((result start)) (set! start (op start constant)) result)) (define arithmetic (sequence +)) (define geometric (sequence *)) (map (arithmetic 1 3) '(1 2 3 4)) ;; => (1 4 7 10) (map (geometric 1 2) '(1 2 3 4)) ;; => (1 2 4 8)
Expansion:
(define (((sequence op) start constant) . rest) (let ((result start)) (set! start (op start constant)) result)) => (define ((sequence op) start constant) (lambda rest (let ((result start)) (set! start (op start constant)) result))) => (define (sequence op) (lambda (start constant) (lambda rest (let ((result start)) (set! start (op start constant)) result)))) => (define sequence (lambda (op) (lambda (start constant) (lambda rest (let ((result start)) (set! start (op start constant)) result)))))
Sweet!!