[plt-scheme] Currying functions?

From: Danny Yoo (dyoo at hkn.eecs.berkeley.edu)
Date: Fri Feb 3 20:56:02 EST 2006


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!



Posted on the users mailing list.