# Inferable Parameters

Functional programming tends to express most dependencies as simple function parameterization. This is clean and powerful, but it sometimes leads to functions that take many parameters and call trees where the same value is passed over and over again in long call chains to many functions. Inferable parameters can help here since they enable the compiler to synthesize repetitive arguments instead of the programmer having to write them explicitly.

For example, given the implied instances defined previously, a maximum function that works for any arguments for which an ordering exists can be defined as follows:

``````def max[T](x: T, y: T) given (ord: Ord[T]): T =
if (ord.compare(x, y) < 1) y else x
``````

Here, `ord` is an inferable parameter. Inferable parameters are introduced with a `given` clause. The `max` method can be applied as follows:

``````max(2, 3) given IntOrd
``````

The `given IntOrd` part provides the `IntOrd` instance as an argument for the `ord` parameter. But the point of inferable parameters is that this argument can also be left out (and it usually is). So the following applications are equally valid:

``````max(2, 3)
max(List(1, 2, 3), Nil)
``````

## Anonymous Inferable Parameters

In many situations, the name of an inferable parameter of a method need not be mentioned explicitly at all, since it is only used in synthesized arguments for other inferable parameters. In that case one can avoid defining a parameter name and just provide its type. Example:

``````def maximum[T](xs: List[T]) given Ord[T]: T =
xs.reduceLeft(max)
``````

`maximum` takes an inferable parameter of type `Ord` only to pass it on as an inferred argument to `max`. The name of the parameter is left out.

Generally, inferable parameters may be given either as a parameter list `(p_1: T_1, ..., p_n: T_n)` or as a sequence of types, separated by commas. To distinguish the two, a leading `(` always indicates a parameter list.

## Inferring Complex Arguments

Here are two other methods that have an inferable parameter of type `Ord[T]`:

``````def descending[T] given (asc: Ord[T]): Ord[T] = new Ord[T] {
def compare(x: T, y: T) = asc.compare(y, x)
}

def minimum[T](xs: List[T]) given Ord[T] =
maximum(xs) given descending
``````

The `minimum` method's right hand side passes `descending` as an explicit argument to `maximum(xs)`. With this setup, the following calls are all well-formed, and they all normalize to the last one:

``````minimum(xs)
maximum(xs) given descending
maximum(xs) given (descending given ListOrd)
maximum(xs) given (descending given (ListOrd given IntOrd))
``````

## Mixing Inferable And Normal Parameters

Inferable parameters can be freely mixed with normal parameters. An inferable parameter may be followed by a normal parameter and vice versa. There can be several inferable parameter lists in a definition. Example:

``````def f given (u: Universe) (x: u.T) given Context = ...

implied global for Universe { type T = String ... }
implied ctx for Context { ... }
``````

Then the following calls are all valid (and normalize to the last one)

``````f("abc")
(f given global)("abc")
f("abc") given ctx
(f given global)("abc") given ctx
``````

## Querying Implied Instances

A method `the` in `Predef` creates an implied instance of a given type. For example, the implied instance of `Ord[List[Int]]` is generated by

``````the[Ord[List[Int]]]  // reduces to ListOrd given IntOrd
``````

The `the` method is simply defined as the (non-widening) identity function over an inferable parameter.

``````def the[T] given (x: T): x.type = x
``````

Functions like `the` that have only inferable parameters are also called context queries.

## Syntax

Here is the new syntax of parameters and arguments seen as a delta from the standard context free syntax of Scala 3.

``````ClsParamClause    ::=  ...
|  ‘given’ (‘(’ [ClsParams] ‘)’ | ContextTypes)
DefParamClause    ::=  ...
|  InferParamClause
InferParamClause  ::=  ‘given’ (‘(’ DefParams ‘)’ | ContextTypes)
ContextTypes      ::=  RefinedType {‘,’ RefinedType}

InfixExpr         ::=  ...
|  InfixExpr ‘given’ (InfixExpr | ParArgumentExprs)
``````