## SRFI 232: Flexible curried procedures

This egg provides curried, a lambda-like form that creates flexible curried procedures. These procedures can be applied to arguments one by one, or all at once.

## SRFI description

This page informally documents the forms exported by the egg. For a full description of SRFI 232, see the SRFI document.

## Author

by Wolfgang Corcoran-Mathe, based on the lambda* form created by Jason Hemann and Daniel P. Friedman.

## Informal specification

[syntax] (curried formals body)

formals is anything that could appear as the formals argument of a lambda expression. As with lambda, body is a sequence of one or more expressions.

Normally, a curried evaluates to a procedure which can be applied to any number of arguments. If it is applied to fewer parameters than its formals list indicates, then the given arguments are bound and a new curried procedure which accepts more parameters is returned. When all parameters have been bound, the body of the procedure is evaluated. For example,

```(let* ((foo0 (curried (x y z) (list x (list y z))))
(foo1 (foo0 'a 'b)))
(foo1 'c))
;; => (a (b c))```

Here, foo0 is applied to two arguments, giving another procedure in which x is bound to a and y to b. This is then applied to c, which gives a value for z. All of the original parameters now have bindings, so the body of the procedure is evaluated.

curried procedures can also be applied "all at once":

`(foo0 'a 'b 'c) ; => (a (b c))`

If a normal curried procedure is applied to too many parameters (i.e. more than appear in its formals list), then the rest are passed to the value of the body (which must be a procedure):

```(let ((bar (curried (a b)
(lambda (c d) (+ (* a b) (- c d))))))
(bar 2 3 7 5))
; => 8```

A curried procedure with a "dotted-tail" formals list will bind a list of any excess arguments to the final parameter:

```(let ((foo (curried (a b . rest)
(apply + (* a b) rest))))
(list ((foo 2) 3 4)
(foo 2 3 4 5)
(foo 2 3)))
;; => (10 15 6)```

The procedure is applied as soon as all of the normal parameters have bindings. So, in the above example, (foo 2 3) binds rest to ().

There are a few important corner cases. A curried procedure with an empty formals list evaluates to its body:

`(curried () 'b) ; => b`

If formals is a single identifier, then curried works like lambda:

```(let ((baz (curried xs (list (car xs) (cdr xs)))))
(baz 2 3 4 5))
; => (2 (3 4 5))```
[syntax] (define-curried (p-name . formals) expr ...)

Defines p-name to be a new curried procedure. Equivalent to

```(define ⟨p-name)
(curried formals expr ...))```

### More examples

#### Simple currying

Here, curried is used to create procedures which can be concisely parameterized:

```(import (only (srfi 1) fold))
(define-curried (add* x y) (+ x y))

(map (add* 2) '(1 2 3))
; => (3 4 5)

(define-curried (fold* proc base lis)
(fold proc base lis))

(let ((sum (fold* + 0))
(product (fold* * 1))
(lis '(1 2 3 4 5)))
(list (sum lis) (product lis)))
; => (15 120)```

#### Curried polyvariadic procedures

("Polyvariadic" = "with dotted-tail formals".)

```(define foo (curried (a b . rest) (list a b rest)))

((foo 1) 2 3 4) ; => (1 2 (3 4))

((foo 'a) 'b) ; => (a b ())```

#### Extra arguments

```((curried (a)
(curried (b)
(curried (c) (+ a b c)))) 1 2 3) ; => 6```

#### Currying with nullary procedures

Since nullary curried expressions evaluate to their bodies, application “passes through” any number of such expressions:

```((curried () (curried (x y) (+ x y))) 2 3)
;; => 5

(((curried (x)
(curried ()
(curried (y z)
(list x (* y z))))) 4 5) 6)
;; => (4 30)```

### Author & maintainer

Wolfgang Corcoran-Mathe

Contact: wcm at sigwinch dot xyzzy minus the zy

GitHub

### Version history

0.1
(2022-05-13) Ported to CHICKEN 5.