# Context Functions

*Context functions* are functions with (only) context parameters. Their types are *context function types*. Here is an example of a context function type:

```
type Executable[T] = ExecutionContext ?=> T
```

Context functions are written using `?=>`

as the "arrow" sign. They are applied to synthesized arguments, in the same way methods with context parameters are applied. For instance:

```
given ec: ExecutionContext = ...
def f(x: Int): ExecutionContext ?=> Int = ...
// could be written as follows with the type alias from above
// def f(x: Int): Executable[Int] = ...
f(2)(using ec) // explicit argument
f(2) // argument is inferred
```

Conversely, if the expected type of an expression `E`

is a context function type `(T_1, ..., T_n) ?=> U`

and `E`

is not already an context function literal, `E`

is converted to a context function literal by rewriting it to

```
(x_1: T1, ..., x_n: Tn) ?=> E
```

where the names `x_1`

, ..., `x_n`

are arbitrary. This expansion is performed before the expression `E`

is typechecked, which means that `x_1`

, ..., `x_n`

are available as givens in `E`

.

Like their types, context function literals are written using `?=>`

as the arrow between parameters and results. They differ from normal function literals in that their types are context function types.

For example, continuing with the previous definitions,

```
def g(arg: Executable[Int]) = ...
g(22) // is expanded to g((ev: ExecutionContext) ?=> 22)
g(f(2)) // is expanded to g((ev: ExecutionContext) ?=> f(2)(using ev))
g((ctx: ExecutionContext) ?=> f(3)) // is expanded to g((ctx: ExecutionContext) ?=> f(3)(using ctx))
g((ctx: ExecutionContext) ?=> f(3)(using ctx)) // is left as it is
```

### Example: Builder Pattern

Context function types have considerable expressive power. For instance, here is how they can support the "builder pattern", where the aim is to construct tables like this:

```
table {
row {
cell("top left")
cell("top right")
}
row {
cell("bottom left")
cell("bottom right")
}
}
```

The idea is to define classes for `Table`

and `Row`

that allow the addition of elements via `add`

:

```
class Table:
val rows = new ArrayBuffer[Row]
def add(r: Row): Unit = rows += r
override def toString = rows.mkString("Table(", ", ", ")")
class Row:
val cells = new ArrayBuffer[Cell]
def add(c: Cell): Unit = cells += c
override def toString = cells.mkString("Row(", ", ", ")")
case class Cell(elem: String)
```

Then, the `table`

, `row`

and `cell`

constructor methods can be defined with context function types as parameters to avoid the plumbing boilerplate that would otherwise be necessary.

```
def table(init: Table ?=> Unit) =
given t: Table = Table()
init
t
def row(init: Row ?=> Unit)(using t: Table) =
given r: Row = Row()
init
t.add(r)
def cell(str: String)(using r: Row) =
r.add(new Cell(str))
```

With that setup, the table construction code above compiles and expands to:

```
table { ($t: Table) ?=>
row { ($r: Row) ?=>
cell("top left")(using $r)
cell("top right")(using $r)
}(using $t)
row { ($r: Row) ?=>
cell("bottom left")(using $r)
cell("bottom right")(using $r)
}(using $t)
}
```

### Example: Postconditions

As a larger example, here is a way to define constructs for checking arbitrary postconditions using an extension method `ensuring`

so that the checked result can be referred to simply by `result`

. The example combines opaque type aliases, context function types, and extension methods to provide a zero-overhead abstraction.

```
object PostConditions:
opaque type WrappedResult[T] = T
def result[T](using r: WrappedResult[T]): T = r
extension [T](x: T)
def ensuring(condition: WrappedResult[T] ?=> Boolean): T =
assert(condition(using x))
x
end PostConditions
import PostConditions.{ensuring, result}
val s = List(1, 2, 3).sum.ensuring(result == 6)
```

**Explanations**: We use a context function type `WrappedResult[T] ?=> Boolean`

as the type of the condition of `ensuring`

. An argument to `ensuring`

such as `(result == 6)`

will therefore have a given of type `WrappedResult[T]`

in scope to pass along to the `result`

method. `WrappedResult`

is a fresh type, to make sure that we do not get unwanted givens in scope (this is good practice in all cases where context parameters are involved). Since `WrappedResult`

is an opaque type alias, its values need not be boxed, and since `ensuring`

is added as an extension method, its argument does not need boxing either. Hence, the implementation of `ensuring`

is as about as efficient as the best possible code one could write by hand:

```
val s =
val result = List(1, 2, 3).sum
assert(result == 6)
result
```

### Reference

For more information, see the blog article, (which uses a different syntax that has been superseded).