In order not to derail Darwin, again … - #51 by michaelCTS , I’ll ask the question here: does nix-lang have structural pattern matching similar to python , rust ?
For example this is possible in rust (syntax might not be correct, but you get the idea)
match platform, arch {
"darwin", * => darwin_package,
"openbsd", "x86_64" => openbsd_x86_64_package,
* => default_package
}
builtins.match is for regular expressions and the doc doesn’t point out the existence of a switch of something similar.
If I’m not mistaken, nix-lang is a functional programming language and pattern matching came from that paradigm.
uep
June 23, 2023, 8:07am
2
Nix has patterns in function arguments, which can be either:
a single value binding (of any type - scalar, list, attrset, …)
attributes of an attrset, destructured to single bindings (with ...
to allow more arguments, and ?
to allow defaults for missing attrs)
a combination of the two, via the @
syntax.
See: Language Constructs - Nix Reference Manual for more details.
It does not, as far as I’m aware, have the control-flow / switch style match construct using those patterns. Please tell me if I’m wrong on this point, or if there’s a useful library function to approximate it. Since functions are anonymous and lazy, I guess you just use a function.
Rust syntax aside
the example you gave looks like this:
match (platform, arch) {
("darwin", _) => darwin_package,
("openbsd", "x86_64") => openbsd_x86_64_package,
(_, _) => default_package
}
but the idea was otherwise clear, indeed.
Nix doesn’t have pattern matching as builtin syntax, but nixpkgs.lib has attrsets.matchAttrs , and you can kind-of build pattern matching with that:
# nix repl --extra-experimental-features 'flakes repl-flake' nixpkgs
nix-repl> if_let = v: p: if lib.attrsets.matchAttrs p v then v else null
nix-repl> if_let { platform = "darwin"; arch = "aarch64"; } { platform = "darwin"; }
{ arch = "aarch64"; platform = "darwin"; }
nix-repl> if_let { platform = "darwin"; arch = "aarch64"; } { platform = "linux"; }
null
nix-repl> match = v: l: builtins.elemAt (
lib.lists.findFirst (
x: (if_let v (builtins.elemAt x 0)) != null
) null l
) 1
nix-repl> match { platform = "linux"; arch = "aarch64"; } [
[ { platform = "darwin"; } "it's macOS" ]
[ { platform = "linux"; } "it's Linux" ]
]
"it's Linux"
Is this what you’re looking for?
1 Like
I think this would be a great addition to the lib! Looks exactly like what I’m looking for. Thank you!
1 Like