# Exercise solution: Generalization of curry-2 and curry-3

Here is a solution with some explaining comments. The curry function was suggested by Søren Envoldsen (student in the PP 2013 class).

```
; f is a function with n parameters. Return a curried version of f.
; Søren Enevoldsen, Sept. 12, 2013:
(define (curry f n)
(curry-internal f n '()))

; This function generates a nesting of lambda expression, each accepting a single parameter.
; While nesting lambda expressions (lambda (x) ...) into each other we form a list of all parameters in the last parameter.
; When all nested lambda expressions have been formed, (reverse args) is the list of parameters. f is applied on (reverse args).
; Sample rewritings, currying -:
;  (curry - 3) =>
;  (curry-internal - 3 ()) =>
;  (lambda(x) (curry-internal - 2 (list x))) =>
;  (lambda (x) (lambda (y) (curry-internal - 1 (list y x)))) =>
;  (lambda (x) (lambda (y) (lambda (z) (apply - (reverse (list z y x))))))
(define (curry-internal f n args)
(if (= n 1)
(lambda (x) (apply f (reverse (cons x args))))
(lambda (x) (curry-internal f (- n 1) (cons x args)))))

; The following variant of uncurry has been suggested by KN:
; The function cf is a curried function with n levels of parameters.
; Return an uncuried variant of cf that - flatly - accepts n parameters.
(define (uncurry cf n)
(lambda pars
(if (= (length pars) n)
(apply-n n cf pars)
(error "Illegal function signature"))))

; This function successively applies the curried functions.
; parameters holds the remaing parameter list, to be used step-wise by the forthcoming calls of the single-parameter functions.
; At each level, a lambda expression is applied on the first element of parameters. The tail of parameters is passed to the next call of apply-n.
(define (apply-n n cf parameters)
(if (= n 1)
(cf (car parameters))
(apply-n (- n 1) (cf (car parameters)) (cdr parameters))))
```

Here are some example uses:

```
> (define cp4 (curry + 4))

> ((((cp4 1) 2) 3) 4)
10

> (define p4 (uncurry cp4 4))
> (p4 1 2 3 4)
10

> (p4 1 2 3 4 6 7 8)
Illegal function signature

> (p4 1 2 3)
Illegal function signature

> (define x (uncurry (curry + 4) 4))
> (x 1 2 3 4)
10

> (x 1 2 3 4 5)
Illegal function signature
```