(define section (lambda (proc . sparams) (lambda params (let kernel ((sparams sparams) (params params) (acc null)) (cond ; If we've run out of all parameters, apply the procedure ((null? sparams) (if (null? params) (apply proc (reverse acc)) (error "Too many parameters"))) ; If the next section parameter is a "hole", use the next ; input parameter. ((eq? (car sparams) '?) (if (not (null? params)) (kernel (cdr sparams) (cdr params) (cons (car params) acc)) (error "Too few parameters"))) ; Otherwise, use the section parameter. (else (kernel (cdr sparams) params (cons (car sparams) acc)))))))) ; Challenge: Write sect so that it generates the "code" (as a list) for the new ; procedure ; For example ; > (sect + 1 2 '? 3 '?) ; (lambda (v1 v2) (# 1 2 v1 3 v2)) (define sect (lambda (proc . params) ; At the end (let kernel ((remaining-params params) (newparams null) (body (list proc))) (cond ((null? remaining-params) (list 'lambda (reverse newparams) (reverse body))) ((eq? '? (car remaining-params)) (let ((newparam (gensym))) (kernel (cdr remaining-params) (cons newparam newparams) (cons newparam body)))) (else (kernel (cdr remaining-params) newparams (cons (car remaining-params) body))))))) (define genvar (lambda (val) (string->symbol (string-append "v" (number->string val))))) (define section (lambda stuff (eval (apply sect stuff)))) (define foo (lambda (a b) (+ (* a a a) (* b b)))) ;Some interesting examples to try in the interactions window: ;(define bar (section foo '? 2)) ;(define baz (section 'foo '? 2)) ;(bar 3) ;(baz 3) ;(define foo +) ;(bar 3) ;(baz 3)