# Anaphora and Lambdas

Eucalypt doesn't have a lambda syntax in itself and prefers to encourage other approaches in most cases where you would use a lambda.

- named functions
- function values from composites, combinators, partials
- anaphoric expressions, blocks or strings

However, through the combination of two Eucalypt features, namely
*block anaphora* and *generalised lookup*, you can express arbitrary
lambdas as we'll see below.

The various alternatives are considered one by one.

## Named functions

Very likely, the clearest way to square a list of numbers is to map an
explicitly named `square`

function across it.

```
square(x): x * x
squares: [1, 2, 3] map(square) //=> [1, 4, 9]
```

The drawbacks of this are: - polluting a namespace with a name that is need only once - arguably, a slightly tedious verbosity

The first can be dealt with as follows:

```
squares: { square(x): x * x }.([1, 2, 3] map(square)) //=> [1, 4, 9]
```

This exploits a feature called *generalised lookup*.

Why "generalised lookup"? In the simple case below, the dot signifies
the "lookup" of key `a`

in the block preceding the dot:

```
x: { a: 3 b: 4 }.a //=> 3
```

We can generalise this by allowing arbitrary expressions in place of
the `a`

by evaluating the expression after the dot in the context of
the namespace introduced by the block to the left.

```
x: { a: 3 b: 4 }.(a + b) //=> 7
```

It works for any expression after the dot:

```
x: { a: 3 b: 4 }.[a, b] //=> [3, 4]
y: { a: 3 b: 4 }.{ c: a + b } //=> { c: 7 }
z: { a: 3 b: 4 }."{a} and {b}" //=> "3 and 4"
```

Warning

This is very effective for short and simple expressions but quickly gets very complicated and hard to understand if you use it too much. Nested or iterated generalised lookups are usually a bad idea.

In the `squares`

example above, generalised lookup is used to restrict
the scope in which `square`

is visible right down to the only
expression which needs it.

However in the case of a simple expression like the squaring example,
a neater approach is to use *expression anaphora*.

## Expression Anaphora

Any expression can become a function by referring to implicit parameters known as expression anaphora.

These parameters are called `_0`

, `_1`

`_2`

, and so on. There is also
an unnumbered anaphorus, `_`

, which we'll come back to.

Just referring to these parameters is enough to turn an expression into a lambda.

So an expression that refers `_0`

and `_1`

actually defines a function
accepting two parameters:

```
xs: zip-with(f, [1, 2, 3], [1, 2, 3]) //=> [3, 6, 9]
# or more succinctly
xs: zip-with(_0 + 2 * _1, [1, 2, 3], [1, 2, 3]) //=> [3, 6, 9]
```

Warning

Again, anaphora intended for use in simple cases where they are readable and readily understood. The scope of the implicit parameters is not easy to work out in complicated contexts. (It does not extend past catenation or commas in lists or function application tuples.) Anaphoric expressions are not, and not intended to be, a fully general lambda syntax. Unlike explicit lambda constructions, you cannot nest anaphoric expressions.

```
squares: [1, 2, 3] map(_0 * _0) //=> [1, 4, 9]
```

In cases where the position of the anaphora in the expression matches
the parameter positions in the function call, you can omit the
numbers. So, for instance, `_0 + _1`

can simply be written `_ + _`

,
and `_0 * _1 + x * _2`

can be written `_ * _ + x * _`

.

Each `_`

represents a *different* implicit parameter, which is why we
had to write `_0 * _0`

in our squares example - it was important that
the same parameter was reference twice.

Sometime you need explicit parentheses to clarify the scope of expression anaphora:

```
block: { a: 1 b: 2 }
x: block (_.a) //=> 1
y: block lookup(:a) //=> 1
#
# BUT NOT: block _.a
#
```

## Sections

Even more conciseness is on offer in some cases where the anaphora can
be entirely omitted. Eucalypt will automatically insert anaphora
when it detects *gaps* in an expression based on its knowledge of an
operator's type.

So it will automatically read `(1 +)`

as `(1 + _)`

, for example,
defining a function of one parameter. Or `(*)`

as `(_ * _)`

, defining
a function of two parameters. The parentheses may not even be
necessary to delimit the expression:

```
x: foldl(+, 0, [1, 2, 3]) = 6
```

Again, use of sections is recommended only for short expressions or where the intention is obvious. This level of tersity can lead to baffling code if abused.

## Block Anaphora

Expression anaphora are scoped by an expression which is roughly defined as something within parentheses or something which can be the right hand side of a declaration.

Sometimes however you would like to define a block-valued function.
Imagine you wanted a two-parameter function which placed the
parameters in a block with keys `x`

and `y`

:

```
f(x, y): {x: x y: y }
```

An attempt to define this using expression anaphora would fail. This defines a block with two identity functions:

```
f: {x: _ y: _ }
```

Instead, you can use *block anaphora* which are scoped by the block
that contains them.

The block anaphora are named `•0`

, `•1`

, `•2`

with a special
unnumbered anaphor `•`

, playing the same role as `_`

does for
expression anaphora.

`•`

is the BULLET character (usually Option-8 on a Mac but you may
find other convenient ways to type it). The slightly awkward character
is chosen firstly because it looks like a hole and therefore makes
sense as a placeholder, and secondly to discourage overuse of the
feature...

The following defines the function we want

```
f: { x: • y: • }
```

...and can, of course, be used

```
x: [[1, 2], [3, 4], [5, 6]] map({ x: • y: • } uncurry)
```

## Pseudo-lambdas

Astute observers may realise that by combining generalised lookup and block anaphora you end up with something that's not a million miles away from a lambda syntax:

```
f: { x: • y: • }.(x + y)
```

Indeed this does allow declaration of anonymous functions with named parameters and can occasionally be useful but it still falls short of a fully general lambda construction because it cannot (at least for now) be nested.

## String Anaphora

Analogously, Eucalypt's string interpolation syntax allows the use of
anaphora `{0}`

, `{1}`

, `{2}`

and the unnumbered `{}`

to define
functions which return strings.

```
x: [1, 2, 3] map("#{}") //=> ["#1", "#2", "#3"]
```

## Summary

There are lots of ways to define functions but the clearest is just defining them with names using function declarations and for anything even slightly complicated this should be the default. The only things you should be tempted to define on the spot are things that are simple enough that the various species of anaphora can handle them neatly.