about summary refs log tree commit diff
path: root/users/sterni/nix/flow
diff options
context:
space:
mode:
Diffstat (limited to 'users/sterni/nix/flow')
-rw-r--r--users/sterni/nix/flow/default.nix76
1 files changed, 53 insertions, 23 deletions
diff --git a/users/sterni/nix/flow/default.nix b/users/sterni/nix/flow/default.nix
index a9fe3c673532..b5783bd86deb 100644
--- a/users/sterni/nix/flow/default.nix
+++ b/users/sterni/nix/flow/default.nix
@@ -6,47 +6,77 @@ let
     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);
 
-  /* cond :: [ [ bool any ] ] -> 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.
-   *
-   * Example:
-   *
-   * cond [
-   *   [ (builtins.isString true) 12 ]
-   *   [ (3 == 2) 13 ]
-   *   [ true 42 ]
-   * ]
-   *
-   * => 42
+  /* 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:
+  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 "cond: exhausted all conditions"
+    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 builtins.head c
+        if b
         then builtins.elemAt c 1
-        else cond (builtins.tail conds);
+        else switch x (builtins.tail conds);
 
-  # TODO(sterni): condf or magic
-  # like <nixpkgs/pkgs/build-support/coq/extra-lib.nix>
 
 
 in {
   inherit
     cond
+    switch
     ;
 }