# x => … — lambdas, with or without parameter types

> A lambda is an inline function: a parameter list, `=>`, and a body. Its parameter types come from where it is used, or you write them yourself — `(Order o) => o.Total` — and then they must match that position exactly.

<!-- id: function-lambda · area: function · stability: stable · html: https://osysharp.com/reference/function/lambda/ -->

## Summary        {#summary}
A lambda is an inline function — `x => x.Total > 10m`. Where it is passed decides its parameter types: in
`orders.Where(o => …)` the `o` is an `Order` because `Where` over orders passes one. You may also write the types
yourself, as in C#: `(Order o) => o.Total`. A declared type is then checked against the one the position passes,
and where nothing passes one — `var twice = (int x) => x * 2;` — the declared types are what type the lambda.

## Signature      {#signature}
```osy syntax
x => body                    // one parameter, typed by where the lambda is used
(a, b) => body               // several parameters
(int a, string b) => body    // EXPLICITLY typed — all of them, or none
() => body                   // no parameters
x => { statements }          // a block body, wherever the lambda runs (not a query over stored rows)
```

## Description    {#description}

### Where do a lambda's parameter types come from?   {#target}
From the position it is written in — its TARGET. A LINQ clause passes the element (`xs.Where(x => …)` over a
`List<int>` binds `x` as `int`), a `Func<T, R>` slot passes its `T`s, and an index-aware `Select((x, i) => …)` passes
the element and its `int` position. That is why you rarely need to write a type at all.

```osy title="the target supplies the types" test app=function-lambda
enum Pace { Slow, Fast }
entity Delivery { [Required] decimal Weight; Pace Pace; }

decimal Heavy() { return Delivery.Where(d => d.Weight > 20m).Sum(d => d.Weight); }
List<int> Positions(List<int> xs) { return xs.Select((x, i) => x * i).ToList(); }
```

### Can I write the parameter types myself?   {#explicit-types}
Yes — exactly as in C#. Write each parameter as `Type name`, and give every parameter a type or none of them:

```osy title="explicitly typed parameters, in LINQ and in a Func" test app=function-lambda
int FastOnes() {
  return Delivery.Where((Delivery d) => d.Pace == Pace.Fast)
                 .Select((Delivery d) => d.Pace)
                 .Where((Pace p) => p == Pace.Fast)
                 .Count();
}
int Longest(List<string> words) { return words.Select((string w, int i) => w.Length + i).Max() ?? 0; }
int Combine() { Func<int, string, int> f = (int n, string s) => n + s.Length; return f(1, "ab"); }
```

A typed parameter reads the same as an untyped one inside the body; the type is a statement about it, and the
compiler holds you to it.

### What if the type I write is not the one the position passes?   {#mismatch}
It is a compile error naming both, as in C# (CS1678). A declared type is not a conversion: `(long x) =>` over a
`List<int>` is refused rather than widened, and `(int t) =>` over a sequence of `decimal` is refused rather than
truncated. Nullability counts for a value type — `int?` is not `int`.

```text
the lambda declares `x` as `long`, but its target supplies it, so `x` is `int` — a lambda's declared parameter
types must match its target exactly (C#'s CS1678). Write `(int x) => …`, or leave the types off and let the target
supply them: `(x) => …`.
```

A list that types some parameters and not others — `(int x, i) => …` — is refused too (C#'s CS0748), with both
spellings that work.

### Can a lambda stand on its own, with no target?   {#natural-type}
Only when its parameters are typed. `var twice = (int x) => x * 2;` has everything it needs: the declared `int` types
`x`, and the body's type is what it returns, so `twice` is a `Func<int, int>` and `twice(3)` is an `int` — C#'s
natural type for a lambda. An UNTYPED lambda there has nothing to bind its parameters from and is refused (C#'s
CS0815); give it a type, or declare the variable as a `Func<…>`.

```osy title="a typed lambda held in a variable" test app=function-lambda
int Twice(int n) {
  var twice = (int x) => x * 2;          // Func<int, int>, from the declared type
  Func<int, int> alsoTwice = x => x * 2; // the same, typed by the variable instead
  return twice(n) + alsoTwice(n);
}
```

### Can a lambda have a block body?   {#block-body}
Yes — `x => { …; return y; }`, exactly as in C#, wherever the lambda RUNS: a `Func`/`Action` held in a variable or
passed to a parameter, and a LINQ verb over a list already in memory. The block holds anything a function body can —
locals, loops, `if`, `try`/`catch`, calls — and its `return` answers the lambda. A `Func` lambda must return a value
on every path (C#'s CS1643); an `Action` lambda's `return` carries none (CS8030).

```osy title="block lambdas as a Func, an Action and a LINQ selector" run app=function-lambda
[Test]
void Block_Lambdas_Run_Their_Statements() {
  Func<int, int> fold = x => { var t = x * 2; while (t > 10) { t -= 10; } return t; };
  int calls = 0;
  Action note = () => { calls++; };
  var lengths = new List<string> { "kite", "ox", "harbour" }.Select(w => {
    note();
    if (w.Length > 4) { return w.Length * 10; }
    return w.Length;
  }).ToList();
  Assert.Equal(16, fold(4) + fold(9));
  Assert.Equal(76, lengths.Sum());
  Assert.Equal(3, calls);
}
```

Two places take an expression body only. A lambda that becomes part of a QUERY over stored rows is translated to
SQL, and a block has no SQL form — read the rows first (`.ToList()`) and run the block over the list, or move the
statements into a function. And a render expression is evaluated where no call can run, so a lambda invoked there
keeps an expression body. A block lambda also cannot wait inside itself for the other side or a durable timer:
compute what it waits for before it runs.

### Can a lambda change a variable of the code around it?   {#captures}
Yes, while it runs in the function that declared it — the lambda and the function share the variable, as in C#.
Hold the lambda in a local and call it:

```osy title="a lambda that writes a variable it shares with its function" run app=function-lambda
[Test]
void A_Lambda_Shares_What_It_Writes() {
  int count = 0;
  Action bump = () => count++;
  bump();
  bump();
  Assert.Equal(2, count);
}
```

What it may not do is LEAVE that function while it writes such a variable — passed to another function, stored in a
field or a list, returned, or not held in a local at all. It would then run where the variable is not, so that is a
compile error that says so. Have such a lambda return the new value instead, and assign it where the variable lives.

### Does a lambda see a variable that changes after it is made?   {#live-captures}
Yes — a lambda captures the VARIABLE, not its value, so it reads what the variable holds when the lambda RUNS, as in
C#. That includes a loop variable a `for` moves on:

```osy title="a lambda reads the current value" run app=function-lambda
[Test]
void A_Lambda_Reads_The_Current_Value() {
  int step = 1;
  Func<int> scaled = () => step * 10;
  step = 5;
  Assert.Equal(50, scaled());

  int total = 0;
  for (int i = 1; i <= 3; i++) {
    Func<int> tenTimes = () => i * 10;
    total += tenTimes();
  }
  Assert.Equal(60, total);
}
```

The same rule as a lambda that writes: it holds while the lambda runs in the function that declared it. One that is
handed on or stored, and reads a variable the function changes afterwards, is refused by name — pass the value to it
as a parameter instead. A lambda passed straight to a call (`Apply(() => k + 1)`) is run by that call before anything
around it can change, so it reads the same value either way.

## Examples       {#examples}
```osy title="typed and untyped lambdas side by side" test app=function-lambda
decimal Weights(List<decimal> ws) {
  var light = ws.Where(w => w < 5m).Sum();                    // typed by the target
  var heavy = ws.Where((decimal w) => w >= 5m).Sum();         // typed by you — and checked
  return light + heavy;
}
```

## See also       {#see-also}
- [Func<T, R>](https://osysharp.com/reference/ui/function-value/) — a `Func<T, R>` parameter or field that takes a lambda and is invoked for its value
- [Querying data](https://osysharp.com/reference/query/index/) — LINQ over your data, where most lambdas are written
- [var](https://osysharp.com/reference/function/var/) — `var`, and what a declaration takes its type from
- [Typed locals](https://osysharp.com/reference/function/typed-locals/) — declaring a local with an explicit type
