Implementing it as a procedure
Stephan H.M.J. Houben 13 Feb 2002 08:05 UTC
Hello list,
I just realised that, with a small modification,
curry-which-isnt-curry can be written as an ordinary
procedure instead of a macro. The only problem is that
ordinary procedures cannot handle improper lists.
This could be fixed by introducing a special marker for
"the rest", e.g. <...>.
Then we get the following code:
(define <> (list "Marker 1"))
(define <...> (list "Marker 2"))
(define (curry-which-isnt-curry proc . params)
(define (substitute-params params args)
(cond
((null? params)
(if (null? args)
'()
(error "Trailing arguments" args)))
((eq? (car params) <...>)
(if (null? (cdr params))
args
(error "Parameters after <...>" (cdr params))))
((eq? (car params) <>)
(if (null? args)
(error "Too few arguments")
(cons (car args)
(substitute-params (cdr params) (cdr args)))))
(else
(cons
(car params)
(substitute-params (cdr params) args)))))
(lambda args
(apply proc (substitute-params params args))))
(define example1 (curry-which-isnt-curry list 1 <> 2 3))
(define example2 (curry-which-isnt-curry vector <> 'b <...>))
This gives then:
(example1 'foo) ==> (1 foo 2 3)
(example2 'foo 'bar 'baz) ==> #(foo b bar baz)
So the advantage of using <...> (or something else) as a marker
is that then this form can be implemented as a procedure.
Don't know if that is considered important, but I think
I should just note it.
Stephan