# Func<T, R>

> A parameter or class field typed `Func<T, R>` takes a lambda and can be invoked for a result, so reusable code can be told HOW to get a value rather than being handed one. It is an expression plus the values it captured, not a compiled closure — which is what keeps it checkable and what makes a typo a compile error.

<!-- id: ui-function-value · area: ui · stability: preview · html: https://osysharp.com/reference/ui/function-value/ -->

## Summary        {#summary}
A component that works over data it doesn't know the shape of needs to be told **how to get** a value, not just
which value:

```osy title="a component told how to read its label" test app=ui-function-value
[Composable] component Labelled(string name, Func<string, string> pick) {
  render { Text(pick(name)); }
}

[Page("/")] [AllowAnonymous]
component Home() {
  render {
    Stack(p: 4) {
      Labelled(name: "ada",   pick: x => x + " (picked)");
      Labelled(name: "grace", pick: x => "<" + x + ">");
    }
  }
}
```

`pick` is a **function value**. It is passed as a lambda and invoked with `pick(name)` wherever a value is wanted.

## Signature      {#signature}
```osy syntax
Func<T, R>          // a parameter that takes a lambda of one argument returning R
Func<T1, T2, R>     // …of two

pick(row)           // invoke it for its value
```

Contrast `Action` / `()`-delegate parameters, which are **callbacks**: they run and produce nothing. A `Func<>`
produces a value and can stand anywhere a value can.

## Description    {#description}

### It is an expression, not a closure   {#expression}
A function value is its **parameter names, its body, and the values it captured**. It is evaluated by binding the
parameters and evaluating the body — the same thing a query lambda (`Where(r => r.Total > 0)`) has always been.

### It captures the surrounding scope, **by value**   {#capture}
The body may read its parameters *and* whatever is in scope where you wrote it. Each outer name is read **once,
where the lambda literal appears** — not later, where it is invoked:

```osy title="an outer name is read where the lambda is WRITTEN, not where it runs" syntax
component Roster() {
  var admins = RoleGrant.Where(g => g.IsAdmin);       // the page's own query

  // `admins` is captured: read here, when this column list is built.
  var columns = [ new GridColumn<User> {
    Name = "Role",
    Value = u => admins.Any(g => g.User == u) ? "Admin" : "User"
  } ];
}
```

**Why by value, and not read later.** A function value travels: a column selector is handed to a grid and invoked
deep inside it, where the names your body reads do not exist at all — so a late read could only ever find nothing.
Reading at the literal is also the answer you want, because the expression that *built* the lambda re-evaluates when
its own inputs change. When `admins` reloads, the column list is rebuilt and a fresh selector replaces the old one.

The one thing to know: a captured value is a **snapshot**. If you mutate a captured list in place, a selector built
before the mutation keeps the value it was given.

### Everything about the call is checked   {#checking}
A slot's declared type is its contract, and all three ways of getting it wrong are compile errors:

| you wrote | you get |
|---|---|
| `pick: (a, b) => a.Title` for a one-argument slot | *takes `Func<Report, string>` — 1 parameter(s), but the lambda declares 2* |
| `pick: x => x.Amount` where the slot returns a string | *the lambda must produce string — it produces int* |
| `pick(a, b)` on a one-argument function | *this verb takes 1 argument(s) — got 2* |
| `var f = x => x;` — a lambda with nothing to bind `x` from | *a lambda needs a target type to bind its parameter from, and this position has none — the same rule as C#'s CS0815. Give it one: pass it to a parameter declared `Func<T, TResult>`, assign it to a member or variable declared with that type, or return it from a function whose return type is one.* |

So a renamed field breaks the build rather than quietly rendering a blank.

### Where it can be used   {#where}
A **function or method parameter**, a **component parameter**, and a **class field**. A lambda written at any of
them is bound from the declared type — the parameter says `Func<string, string>`, so `v` *is* a string and
`v.Length` type-checks:

```osy title="a lambda passed to a parameter" test app=ui-function-value-param
string Apply(Func<string, string> f) { return f("x"); }

class Tally {
  public int Hits = 0;
  public void Each(Action<int> a) { a(1); a(2); }   // an Action parameter takes a lambda too — run for its effect
}

[AllowAnonymous] int Count() {
  var suffix = "!";
  var shout = Apply(v => v + suffix);              // "x!" — the lambda may capture what is in scope
  var t = new Tally();
  t.Each(n => t.Hits = t.Hits + n);                // 3
  return t.Hits + shout.Length;
}
```

The class-field form is what lets a descriptor object carry its own selector, so a caller can describe a set of
columns, filters or sort keys as data:

```osy title="a descriptor object carrying its own selector" test app=ui-function-value-field
class Column {
  public Func<string, string> Value;
  public string Label;
}

[Composable] component Grid(string[] rows, Column[] columns) {
  render {
    Stack(gap: 2) {
      Row(gap: 3) { foreach (var h in columns) { Text(h.Label); } }
      foreach (var r in rows) {
        Row(gap: 3) { foreach (var c in columns) { Text(c.Value(r)); } }
      }
    }
  }
}

[Page("/")] [AllowAnonymous]
component Home() {
  string[] names = ["ada", "grace"];
  render {
    Grid(rows: names, columns: [
      new Column { Value = r => "<" + r + ">", Label = "Wrapped" },
      new Column { Value = r => r + "!",       Label = "Banged" }
    ]);
  }
}
```

The descriptor class can be **generic**, so one shape serves every row type instead of being copied per entity — see
[Generic classes](https://osysharp.com/reference/class/generics/):

```osy title="one generic descriptor instead of a copy per row type" syntax
class Column<T> { public string Label; public Func<T, string> Value; }
new Column<Report> { Label = "Title", Value = r => r.Title }
```

### It is not only a UI thing   {#outside-ui}
Every example above is a component, but a function value is an ordinary value in an ordinary function too: a class
field holds one, and invoking it produces a result wherever a value is wanted.

```osy title="held in a field, invoked in a plain function" test app=ui-function-value-server
class Report { public string Title; public Report(string title) { Title = title; } }
class Column<T> { public string Label; public Func<T, string> Value; }

string TitleOf(string title) {
  var col = new Column<Report> { Label = "Title", Value = r => r.Title };
  return col.Value(new Report(title));
}
```

The one limit: a function value **cannot be held across an `await` that suspends**. What would have to travel is a
body expression plus a captured environment, which is not a storable value — so invoke it before the await and hold
its result instead.

## Examples       {#examples}

```osy title="the same component, told two different things" test app=ui-function-value-two
[Composable] component Show(int n, Func<int, string> fmt) {
  render { Text(fmt(n)); }
}

[Page("/")] [AllowAnonymous]
component Home() {
  render {
    Stack(p: 4) {
      Show(n: 42, fmt: v => "n = " + v);
      Show(n: 42, fmt: v => "[" + v + "]");
    }
  }
}
```

## See also       {#see-also}
- [component](https://osysharp.com/reference/ui/component/) — parameters, state and the render block
- [Slot (child content)](https://osysharp.com/reference/ui/slots/) — the other way to let a caller decide content: a template rather than a value
- [Cell template (your own content in a control's cell)](https://osysharp.com/reference/ui/cell-template/) — per-item templates, which a function value complements rather than replaces
