University of Connecticut

jeffm@cse.uconn.edu

December 7, 1995

Revised March 15, 1997

All code examples were written using PC Scheme version 4.02, although no architecture-specific functions were used.

Evaluatingmult :: Int -> Int -> Int mult x y = x * y

Functions can be built of curried functions as

(or equivalently)double = mult 2

wheredouble = (*) 2

The free variable y in the lambda function becomes statically bound to the argument to(define (mult y) (lambda (x) (* y x)))

and allows one to create constant multiplier functions. Then(lambda (x) (* n x))

would create a doubler, similar to the one described in Haskell above.(define (double x) ((mult 2) x))

This function takes a function and some number of arguments (0 or more) to be applied to that function as arguments, and returns a function expecting more arguments. When the curried function is evaluated with arguments, a complete argument list is created from both the original partial argument list and the new completing argument list (using append), and the original function is evaluated with the new argument list (using apply).(define (curry fun . args) (lambda x (apply fun (append args x))))

The doubler could then be built using the curry function

Curried functions can be built of other curried functions, as in(define double (curry * 2)) => DOUBLE (double 6) => 12

Evaluating each of the functions would yield(define lister1 (curry list 'args)) (define lister2 (curry lister1 'one)) (define lister3 (curry lister2 'two))

Since the original function of the curried function (which is list) can accept multiple arguments, the curried function can also accept multiple arguments(lister1 'foo) => (args foo) (lister2 'bar) => (args one bar) (lister3 'baz) => (args one two baz)

(define lister4 (curry list 'foo 'bar 'baz)) (lister4 'qux 'quux) => (foo bar baz qux quux)

Three support functions are needed for(macro c-lambda (lambda (e) (let* ((params (cadr e)) (expr (caddr e)) (lp (length params))) (lambda args (let ((la (length args))) (cond ((< la lp) (let ((params$ (%c-diff args params)) (expr$ `((lambda ,(%c-isect args params) ,expr) ,@(%c-quote-all args)))) (eval `(c-lambda ,params$ ,expr$)))) ((= la lp) (eval `((lambda ,params ,expr) ,@(%c-quote-all args)))) (else (error `(error ,expr called with ,la arguments expected ,lp)))))))))

;- return those elements of list y that do not have corresponding ;- elements in list x (simple set difference operation) (define %c-diff (named-lambda (%c-r x y) (if (null? x) y (%c-r (cdr x) (cdr y)))));- return those elements of list y that have corresponding ;- elements in list x (simple set intersection) (define %c-isect (named-lambda (%c-b x y) (if (null? x) () (cons (car y) (%c-b (cdr x) (cdr y))))))

;- return x with each element quoted (define (%c-quote-all x) (map (lambda (y) (list 'quote y)) x))

A good example of one of the uses of function currying is with the `
assoc` function.

Evaluating(define assoc-r (c-lambda (lst item) (assoc item lst)))

However, evaluating this function with just the list yields an important result:(assoc-r '((a 1) (b 2) (c 3)) 'b) => (b 3)

The result is a function waiting for the final argument. This result can then be bound to a name and used as a function(assoc-r '((a 1) (b 2) (c 3))) ;- omit item being sought =>

Note that since(define lookup (assoc-r '((a 1) (b 2) (c 3)))) => LOOKUP (lookup 'a) => (a 1) (lookup 'b) => (b 2) (map lookup '(c b a)) => ((c 3) (b 2) (a 1))

From here it is rather straightforward to create a ` c-define`
special form, so that curriable functions can be defined more easily:

Now the(macro c-define (lambda (e) (let ((name (caadr e)) (params (cdadr e)) (expr (caddr e)) (env (environment-parent (the-environment)))) (eval `(set! (access ,name ,env) (c-lambda ,params ,expr))) (list 'quote name))))

Not only does this create a parameter-reversed function, but the function is curriable. It is equivalent to the(c-define (assoc-r lst item) (assoc item lst))