## 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".)

(definefoo (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)

## About this egg

### Author & maintainer

Wolfgang Corcoran-Mathe

Contact: `wcm at sigwinch dot xyzzy minus the zy`

### Repository

### Version history

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

### License

© 2022 Wolfgang Corcoran-Mathe.

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice (including the next paragraph) shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.