{ depot, ... }: let inherit (depot.nix) yants ; inherit (depot.users.sterni.nix) fun ; # we must avoid evaluating any of the sublists # as they may contain conditions that throw condition = yants.restrict "condition" (ls: builtins.length ls == 2) (yants.list yants.any); /* Like the common lisp macro: takes a list of two elemented lists whose first element is a boolean. The second element of the first list that has true as its first element is returned. Type: [ [ bool a ] ] -> a Example: cond [ [ (builtins.isString true) 12 ] [ (3 == 2) 13 ] [ true 42 ] ] => 42 */ cond = conds: switch true conds; /* Generic pattern match-ish construct for nix. Takes a bunch of lists which are of length two and checks the first element for either a predicate or a value. The second value of the first list which either has a value equal to or a function that evaluates to true for the given value. Type: a -> [ [ (function | a) b ] ] -> b Example: switch "foo" [ [ "smol" "SMOL!!!" ] [ (x: builtins.stringLength x <= 3) "smol-ish" ] [ (fun.const true) "not smol" ] ] => "smol-ish" */ switch = x: conds: if builtins.length conds == 0 then builtins.throw "exhausted all conditions" else let c = condition (builtins.head conds); s = builtins.head c; b = if builtins.isFunction s then s x else x == s; in if b then builtins.elemAt c 1 else switch x (builtins.tail conds); in { inherit cond switch ; }