# From argument patterns to pattern matching

**URL:** https://discourse.nixos.org/t/from-argument-patterns-to-pattern-matching/81053
**Category:** Nix
**Created:** [November 8, 2026, 1:22pm UTC](https://discourse.nixos.org/t/from-argument-patterns-to-pattern-matching/81053 "2026-11-08T13:22:38Z")
**Posts on this page:** 2
**Page:** 1

<div class="post-metadata">

### Author: ![volth](https://discourse.nixos.org/user_avatar/discourse.nixos.org/volth/32/272_2.png) [@volth](https://discourse.nixos.org/u/volth)
#### Post date: [November 8, 2026, 1:22pm UTC](https://discourse.nixos.org/t/from-argument-patterns-to-pattern-matching/81053/1 "2026-11-08T13:22:38Z")

</div>

With [`|>` already in use in Nix](https://nix.dev/manual/nix/latest/language/operators.html#pipe-operators), I’ve been thinking about another small language extension.

Nix already has partial functions at the argument-matching level: `{ a, ... }: ...` accepts some arguments and rejects others. Adding just two trivial builtins would let us compose these into pattern matching.

## 1. `builtins.functionDefinedAt`: Ask whether a function accepts an argument

Introduce `builtins.functionDefinedAt f x`, which checks the argument pattern without evaluating the body:

```nix
functionDefinedAt ({ name, ... }: name) {} # false
functionDefinedAt ({ name, ... }: name) { name = "Alice"; } # true
functionDefinedAt ({ name, ... }: name) { name = throw "x"; } # true
functionDefinedAt (x: throw "not called") 42 # true

```

This is about matching the first argument, not predicting whether the function will evaluate successfully. Defaults and unused fields should remain lazy.

For callable sets, we could use a convention: an optional `__defined = x: ...` predicate describes their domain.

## 2. `builtins.functionOrElse`: Combine partial functions

Introduce `builtins.functionOrElse f g`: try `f` if its argument matches; otherwise use `g`.

Using the proposed domain check, the combinator itself can be written in pure Nix:

```nix
functionOrElse = f: g: {
  __functor = self: x:
    if functionDefinedAt f x then f x else g x;

  __defined = x:
    functionDefinedAt f x || functionDefinedAt g x;
};

```

Order matters: the first matching branch wins. An error inside a selected body remains an error; it does not cause fall-through.

(If checking and then destructuring the argument again looks wasteful, an apply-or-fallback primitive, with an `__applyOrElse` hook on functors, can do the matching once - the idea is from Scala’s `PartialFunction`. The same applies to guards described below.)

## 3. Give it an operator

Let `f | g` mean `functionOrElse f g`. Combined with `|>`, this gives us pretty syntax:

```nix
dependency |>
    { package, output }: package.${output}
  | { package }: package
  | package: package

```

Here a dependency can be a package, a wrapper around a package, or a request for a particular output.

The same branches can be used wherever a function is expected:

```nix
builtins.map (
    { file, line, ... }: "${file}:${toString line}"
  | { file, ... }: file
  | _: "<unknown>"
) locations

```

`|` would delimit function branches and bind more tightly than the pipe operators. Branches remain ordinary function values: they can be named, passed around, or assembled elsewhere.

## 4. Optionally, add guards and more sugar

A guard extends the applicability check. It could also express preconditions on package functions while keeping their dependency arguments visible to `callPackage`:

```nix
{ stdenv, ... } if stdenv.hostPlatform.isLinux: ...

```

Literal parameters would just be sugar for equality guards. For example, a build option selecting serial or parallel `make`:

```nix
makeFlags = jobs |>
    1: []
  | n if builtins.isInt n && n > 1: ["-j${toString n}"]
  | _: throw "jobs must be a positive integer";

```

Guards would participate in `functionDefinedAt`: a false guard means the argument does not match. Errors in the guard itself still propagate.

Optional type annotations could also desugar to the same guards. For example, a possible spelling:

```nix
(x :: Int): x + 1

```

could mean:

```nix
x if builtins.isInt x: x + 1

```

---

<div class="post-metadata">

### Author: ![lisanna](https://discourse.nixos.org/user_avatar/discourse.nixos.org/lisanna/32/36988_2.png) [@lisanna](https://discourse.nixos.org/u/lisanna)
#### Post date: [November 8, 2026, 7:59pm UTC](https://discourse.nixos.org/t/from-argument-patterns-to-pattern-matching/81053/2 "2026-11-08T19:59:19Z")

</div>

Sounds like good stuff, although I would caution against expanding the language too much before we have a proper langref. Do you have a prototype to play with?
