[plt-scheme] Currying functions?
On Fri, 3 Feb 2006, Gregory Woodhouse wrote:
> I was just browsing the language manual and came across an interesting
> function: procedure-arity. Now, it just happens that yesterday I had
> occasion to want to create a curried version of a binary operator (as
> part of the evaluator I'm working on, where I wanted to map it across an
> argument list), so I searched for curry and currying in Help Desk and
> found nothing.
Hi Gregory,
You may want to check the Swindle collection; it has a a currying
definition that you might find handy.
http://ja.soegaard.net/planet/html/collects/swindle/readme.txt
> Well, in the case of functions of arity 2 it's easy:
>
> > (define (curry2 f)
> (lambda (x)
> (lambda (y)
> (f x y))))
> > (define a (curry2 +))
> > ((a 2) 3)
> 5
>
> but to create a curried version of an arbitrary function, you need to
> know it's arity. Maybe it's possible to create a curried version of a
> function taking a variable number of arguments, but I'm not sure how it
> would be done.
Maybe something like this would work for you:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(module currify mzscheme
(provide currify)
(define (currify f)
(let ((N (procedure-arity f)))
(letrec
((grab-rest-args
(lambda (n reversed-args-so-far)
(if (= n N)
(apply f (reverse reversed-args-so-far))
(lambda (x)
(grab-rest-args (add1 n)
(cons x reversed-args-so-far)))))))
(cond
((and (number? N) (= N 0)) f)
((number? N)
(lambda (first-arg)
(grab-rest-args 1 (list first-arg))))
(else
(error 'currify
"Don't know how to handle procedure arity ~s" N)))))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
For example:
;;;;;;
> (define take-three (currify (lambda (a b c) (printf "~s~s~s~%" a b c))))
> (take-three 1)
#<procedure:.../dyoo/currify.ss:11:18>
> ((take-three 1) 2)
#<procedure:.../dyoo/currify.ss:11:18>
> (((take-three 1) 2) 3)
123
;;;;;;
Best of wishes!