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