## combinators

Combinators grab-bag.

## Documentation

### Section Combinators

#### Usage

(require-extension section-combinators)

`FUNC` a procedure.

#### left-section

*[procedure]*

`(left-section FUNC ARG0 ...) => procedure`

Returns a procedure that partially applies some of its arguments from the left.

`ARG0 ...` a prefix of the arguments for `FUNC`.

Returns a partially curried procedure.

#### right-section

*[procedure]*

`(right-section FUNC ARG0 ...) => procedure`

Returns a procedure that partially applies some of its arguments from the right.

`ARG0 ...` a suffix of the arguments for `FUNC`.

Returns a partially curried procedure.

#### crop-left

*[procedure]*

`(crop-left FUNC N) => procedure`

Returns a procedure that drops the `N` left arguments before applying `FUNC`.

#### crop-right

*[procedure]*

`(crop-right FUNC N) => procedure`

Returns a procedure that drops the `N` right arguments before applying `FUNC`.

#### reversed

*[procedure]*

`(reversed FUNC) => procedure`

Returns a procedure that reverses the arguments before applying `FUNC`.

#### arguments-chain

*[procedure]*

`(arguments-chain [FUNC0...]) => procedure`

Returns a procedure that applies each `FUNCi` to result of the `FUNCi+1`. `FUNCn` is applied to the arguments.

Examples:

((arguments-chain f g h) arg...) -> (apply f (apply g (apply h arg...)))

((arguments-chain f) arg...) -> (apply f arg...)

((arguments-chain) arg...) -> (list arg...)

#### arguments-each

*[procedure]*

`(arguments-each [FUNC0...]) => procedure`

Returns a procedure that calls each `FUNCi` to the `ARGi`. The result is returned as a `list`. The `FUNC0...` are re-used until the argument list is exhausted.

Examples:

((arguments-each f g h) a b c d e) -> (list (f a) (g b) (h c) (f d) (g e))

((arguments-each f g h) a b c) -> (list (f a) (g b) (h c))

((arguments-each) arg...) -> (list arg...)

#### arguments-all

*[procedure]*

`(arguments-all [FUNC0...]) => procedure`

Returns a procedure that calls each `FUNCi` with all the arguments. The result is returned as a `list`.

Examples:

((arguments-all f g h) a b c) -> (list (f a b c) (g a b c) (h a b c))

((arguments-all) arg...) -> (list arg...)

### Sort Combinators

Except for `make-less-than/key` and `make-equal/key` these are not combinators.

#### Usage

(require-extension sort-combinators)

#### Examples

(group/key identity '(1 2 3 3 4 4 4)) ;=> ((1) (2) (3 3) (4 4 4)) (group/key car '((a 1) (a 2) (b 1))) ;=> '(((a 1) (a 2)) ((b 1))) (sort '(("a" . 1) ("z" . 3) ("b" . 2)) (make-less-than/key first string-ci<?)) ;=> (("a" . 1) ("b" . 2) ("z" . 3))

#### group-by

*[procedure]*

`(group-by FUNC [EQUALITY equal?]) => procedure`

Returns a procedure that takes a list and groups the elements by some key attribute. Uses the single-argument `FUNC` to retrieve key values & the `EQUALITY` function to compare them.

#### group/key

*[procedure]*

`(group/key FUNC LYST [EQUALITY equal?])`

Groups a `LYST` of elements by some key attribute. Uses the single-argument `FUNC` to retrieve key values & the `EQUALITY` function to compare them.

The `LYST` must be in sorted order with respect to the key!

Returns a list of grouped elements.

#### make-less-than/key

*[procedure]*

`(make-less-than/key FUNC [LESS-THAN <]) => {{procedure/2}}`

Returns a two-argument procedure that uses the single-argument `FUNC` to retrieve key values & the two-argument `LESS-THAN` procedure to compare them.

#### make-equal/key

*[procedure]*

`(make-equal/key FUNC [EQUAL =]) => {{procedure/2}}`

Returns a two-argument procedure that uses the single-argument `FUNC` to retrieve key values & the two-argument `EQUAL` procedure to compare them.

### Logical Combinators

#### Usage

(require-extension logical-combinators)

#### andf

*[procedure]*

`(andf OBJECT...)`

Eager version of `and`.

Returns last `(not #f)` `OBJECT` when all `OBJECT...` are `(not #f)`, `#f` otherwise.

#### orf

*[procedure]*

`(orf OBJECT...)`

Eager version of `or`.

Returns first `(not #f)` `OBJECT`, `#f` otherwise.

### Uni Combinators

`C` is a `function`.

`F`, `G` and `H` are `function`.

#### Usage

(require-extension uni-combinators)

#### uni

*[procedure]*

`(uni C F) => procedure`

Returns `(lambda (X) (C (F X)))`.

#### uni2

*[procedure]*

`(uni2 C F) => procedure`

Returns `(lambda (X Y) (C (F X Y)))`.

#### uni3

*[procedure]*

`(uni3 C F) => procedure`

Returns `(lambda (X Y Z) (C (F X Y Z)))`.

#### uni-each

*[procedure]*

`(uni-each C F) => procedure`

Same as `uni`.

#### uni-all

*[procedure]*

`(uni-all C F) => procedure`

Returns `(lambda XS (C (apply F XS)))`.

### Bi Combinators

#### Usage

(require-extension bi-combinators)

#### bi

*[procedure]*

`(bi C F G) => procedure`

Returns `(lambda (X) (C (F X) (G X)))`.

#### bi2

*[procedure]*

`(bi2 C F G) => procedure`

Returns `(lambda (X Y) (C (F X Y) (G X Y)))`.

#### bi3

*[procedure]*

`(bi3 C F G) => procedure`

Returns `(lambda (X Y Z) (C (F X Y Z) (G X Y Z)))`.

#### bi-each

*[procedure]*

`(bi-each C F) => procedure`

Returns `(lambda (X Y) (C (F X) (F Y)))`.

#### bi-all

*[procedure]*

`(bi-all C F G) => procedure`

Returns `(lambda XS (C (apply F XS) (apply G XS)))`.

### Tri Combinators

#### Usage

(require-extension tri-combinators)

#### tri

*[procedure]*

`(tri C F G H) => procedure`

Returns `(lambda (X) (C (F X) (G X) (H X)))`.

#### tri2

*[procedure]*

`(tri2 C F G H) => procedure`

Returns `(lambda (X Y) (C (F X Y) (G X Y) (H X Y)))`.

#### tri3

*[procedure]*

`(tri3 C F G H) => procedure`

Returns `(lambda (X Y Z) (C (F X Y Z) (G X Y Z) (H X Y Z)))`.

#### tri-each

*[procedure]*

`(tri-each C F) => procedure`

Returns `(lambda (X Y Z) (C (F X) (F Y) (F Z)))`.

#### tri-all

*[procedure]*

`(tri-all C F G H) => procedure`

Returns `(lambda XS (C (apply F XS) (apply G XS) (apply H XS)))`.

### Stack Combinators

These treat the argument list as a FORTH-like stack.

The utility is probably low.

#### Usage

(require-extension stack-combinators)

`C` is a `function`.

`F`, `G` and `H` are `function`.

`X`, `Y` and `Z` are `object`.

#### uni

*[procedure]*

`(uni X F C) => procedure`

Returns the result of `(C (F X))`.

*[procedure]*

`(uni F C) => {{procedure/1}}`

*[procedure]*

`(uni C) => {{procedure/1}}`

*[procedure]*

`(uni) => {{procedure/1}}`

Returns a curried procedure.

#### uni2

*[procedure]*

`(uni2 X Y F C) => procedure`

Returns the result of `(C (F X Y))`.

*[procedure]*

`(uni2 F C) => {{procedure/2}}`

*[procedure]*

`(uni2 C) => {{procedure/1}}`

*[procedure]*

`(uni2) => {{procedure/1}}`

Returns a curried procedure.

#### uni3

*[procedure]*

`(uni3 X Y Z F C) => procedure`

Returns the result of `(C (F X Y Z))`.

*[procedure]*

`(uni3 F C) => {{procedure/3}}`

*[procedure]*

`(uni3 C) => {{procedure/1}}`

*[procedure]*

`(uni3) => {{procedure/1}}`

Returns a curried procedure.

#### uni@

*[procedure]*

`(uni@ X F C) => procedure`

Returns the result of `(C (F X))`.

*[procedure]*

`(uni@ F C) => {{procedure/1}}`

Returns a curried procedure.

#### bi

*[procedure]*

`(bi X F G C) => procedure`

Returns the result of `(C (F X) (G X))`.

*[procedure]*

`(bi F G C) => {{procedure/1}}`

*[procedure]*

`(bi F G) => {{procedure/1}}`

*[procedure]*

`(bi C) => {{procedure/2}}`

*[procedure]*

`(bi) => {{procedure/1}}`

Returns a curried procedure.

#### bi2

*[procedure]*

`(bi2 X Y F G C) => procedure`

Returns the result of `(C (F X Y) (G X Y))`.

*[procedure]*

`(bi2 F G C) => {{procedure/2}}`

*[procedure]*

`(bi2 F G) => {{procedure/1}}`

*[procedure]*

`(bi2 C) => {{procedure/2}}`

*[procedure]*

`(bi2) => {{procedure/1}}`

Returns a curried procedure.

#### bi3

*[procedure]*

`(bi3 X Y Z F G C) => procedure`

Returns the result of `(C (F X Y Z) (G X Y Z))`.

*[procedure]*

`(bi3 F G C) => {{procedure/3}}`

*[procedure]*

`(bi3 F G) => {{procedure/1}}`

*[procedure]*

`(bi3 C) => {{procedure/2}}`

*[procedure]*

`(bi3) => {{procedure/1}}`

Returns a curried procedure.

#### bi@

*[procedure]*

`(bi@ X Y F C) => procedure`

Returns the result of `(C (F X) (F Y))`.

*[procedure]*

`(bi@ F C) => {{procedure/2}}`

Returns a curried procedure.

#### tri

*[procedure]*

`(tri X F G H C) => procedure`

Returns the result of `(C (F X) (G X) (H X))`.

*[procedure]*

`(tri F G H C) => {{procedure/1}}`

*[procedure]*

`(tri F G H) => {{procedure/1}}`

*[procedure]*

`(tri C) => {{procedure/3}}`

*[procedure]*

`(tri) => {{procedure/1}}`

Returns a curried procedure.

#### tri2

*[procedure]*

`(tri2 X Y F G H C) => procedure`

Returns the result of `(C (F X Y) (G X Y) (H X Y))`.

*[procedure]*

`(tri2 F G H C) => {{procedure/2}}`

*[procedure]*

`(tri2 F G H) => {{procedure/1}}`

*[procedure]*

`(tri2 C) => {{procedure/3}}`

*[procedure]*

`(tri2) => {{procedure/1}}`

Returns a curried procedure.

#### tri3

*[procedure]*

`(tri3 X Y Z F G H C) => procedure`

Returns the result of `(C (F X Y Z) (G X Y Z) (H X Y Z))`.

*[procedure]*

`(tri3 F G H C) => {{procedure/3}}`

*[procedure]*

`(tri3 F G H) => {{procedure/1}}`

*[procedure]*

`(tri3 C) => {{procedure/3}}`

*[procedure]*

`(tri3) => {{procedure/1}}`

Returns a curried procedure.

#### tri@

*[procedure]*

`(tri@ X Y Z F C) => procedure`

Returns the result of `(C (F X) (F Y) (F Z))`.

*[procedure]*

`(tri@ F C) => {{procedure/3}}`

Returns a curried procedure.

#### dip

*[procedure]*

`(dip X Y F C) => procedure`

Returns the result of `(C (F X) Y)`.

*[procedure]*

`(dip F C) => {{procedure/2}}`

Returns a curried procedure.

#### dup

*[procedure]*

`(dup X C) => procedure`

Returns the result of `(C X X)`.

*[procedure]*

`(dup C) => {{procedure/1}}`

Returns a curried procedure.

#### dupd

*[procedure]*

`(dupd X Y C) => procedure`

Returns the result of `(C X X Y)`.

*[procedure]*

`(dupd C) => {{procedure/2}}`

Returns a curried procedure.

#### swap

*[procedure]*

`(swap X Y C) => procedure`

Returns the result of `(C Y X)`.

*[procedure]*

`(swap C) => {{procedure/2}}`

Returns a curried procedure.

#### drop

*[procedure]*

`(drop X C) => procedure`

Returns the result of `(C)`.

*[procedure]*

`(drop C) => {{procedure/1}}`

Returns a curried procedure.

#### drop/2

*[procedure]*

`(drop/2 X Y C) => procedure`

Returns the result of `(C X)`.

*[procedure]*

`(drop/2 C) => {{procedure/2}}`

Returns a curried procedure.

## Notes

- Inspired by e-mail conversations with Graham Fawcett in Feb '08.
- The procedures
`left-section`and`right-section`from Philip L. Bewig.

## Author

## Version history

- 1.2.0
- Added
`uni/bi/tri-combinators`& more`section-combinators`. - 1.1.0
- Added
`section-combinators`. - 1.0.0
- Chicken 4 release.

## License

Public Domain.