summary refs log tree commit diff
path: root/lib/lists.nix
diff options
context:
space:
mode:
authorProfpatsch <mail@profpatsch.de>2017-03-15 19:05:01 +0100
committerProfpatsch <mail@profpatsch.de>2017-03-19 22:06:49 +0100
commitcb9ff8bfa73fdfa1a38b609e878a52650dfdb682 (patch)
tree6b0d8c2e8c1afd1bf3862019c98473e583f9a3a2 /lib/lists.nix
parentb052a3629463f2f064a0a3da50dbebd73b587651 (diff)
downloadnixpkgs-cb9ff8bfa73fdfa1a38b609e878a52650dfdb682.tar
nixpkgs-cb9ff8bfa73fdfa1a38b609e878a52650dfdb682.tar.gz
nixpkgs-cb9ff8bfa73fdfa1a38b609e878a52650dfdb682.tar.bz2
nixpkgs-cb9ff8bfa73fdfa1a38b609e878a52650dfdb682.tar.lz
nixpkgs-cb9ff8bfa73fdfa1a38b609e878a52650dfdb682.tar.xz
nixpkgs-cb9ff8bfa73fdfa1a38b609e878a52650dfdb682.tar.zst
nixpkgs-cb9ff8bfa73fdfa1a38b609e878a52650dfdb682.zip
lib/lists: rename fold to foldr & improve fold docs
In order to better distinguish foldr from foldl the default name is changed to
foldr, but fold is still a synonym.

Additionally the docs are improved and examples added.
Diffstat (limited to 'lib/lists.nix')
-rw-r--r--lib/lists.nix41
1 files changed, 29 insertions, 12 deletions
diff --git a/lib/lists.nix b/lib/lists.nix
index 5e224921de8..82d5ba0124c 100644
--- a/lib/lists.nix
+++ b/lib/lists.nix
@@ -16,17 +16,22 @@ rec {
   */
   singleton = x: [x];
 
-  /* "Fold" a binary function `op' between successive elements of
-     `list' with `nul' as the starting value, i.e., `fold op nul [x_1
-     x_2 ... x_n] == op x_1 (op x_2 ... (op x_n nul))'.  (This is
-     Haskell's foldr).
+  /* “right fold” a binary function `op' between successive elements of
+     `list' with `nul' as the starting value, i.e.,
+     `foldr op nul [x_1 x_2 ... x_n] == op x_1 (op x_2 ... (op x_n nul))'.
+     Type:
+       foldr :: (a -> b -> b) -> b -> [a] -> b
 
      Example:
-       concat = fold (a: b: a + b) "z"
+       concat = foldr (a: b: a + b) "z"
        concat [ "a" "b" "c" ]
        => "abcz"
+       # different types
+       strange = foldr (int: str: toString (int + 1) + str) "a"
+       strange [ 1 2 3 4 ]
+       => "2345a"
   */
-  fold = op: nul: list:
+  foldr = op: nul: list:
     let
       len = length list;
       fold' = n:
@@ -35,13 +40,25 @@ rec {
         else op (elemAt list n) (fold' (n + 1));
     in fold' 0;
 
-  /* Left fold: `fold op nul [x_1 x_2 ... x_n] == op (... (op (op nul
-     x_1) x_2) ... x_n)'.
+  /* `fold' is an alias of `foldr' for historic reasons */
+  # FIXME(Profpatsch): deprecate?
+  fold = foldr;
+
+
+  /* “left fold”, like `foldr', but from the left:
+     `foldl op nul [x_1 x_2 ... x_n] == op (... (op (op nul x_1) x_2) ... x_n)`.
+
+     Type:
+       foldl :: (b -> a -> b) -> b -> [a] -> b
 
      Example:
        lconcat = foldl (a: b: a + b) "z"
        lconcat [ "a" "b" "c" ]
        => "zabc"
+       # different types
+       lstrange = foldl (str: int: str + toString (int + 1)) ""
+       strange [ 1 2 3 4 ]
+       => "a2345"
   */
   foldl = op: nul: list:
     let
@@ -52,7 +69,7 @@ rec {
         else op (foldl' (n - 1)) (elemAt list n);
     in foldl' (length list - 1);
 
-  /* Strict version of foldl.
+  /* Strict version of `foldl'.
 
      The difference is that evaluation is forced upon access. Usually used
      with small whole results (in contract with lazily-generated list or large
@@ -140,7 +157,7 @@ rec {
        any isString [ 1 { } ]
        => false
   */
-  any = builtins.any or (pred: fold (x: y: if pred x then true else y) false);
+  any = builtins.any or (pred: foldr (x: y: if pred x then true else y) false);
 
   /* Return true iff function `pred' returns true for all elements of
      `list'.
@@ -151,7 +168,7 @@ rec {
        all (x: x < 3) [ 1 2 3 ]
        => false
   */
-  all = builtins.all or (pred: fold (x: y: if pred x then y else false) true);
+  all = builtins.all or (pred: foldr (x: y: if pred x then y else false) true);
 
   /* Count how many times function `pred' returns true for the elements
      of `list'.
@@ -219,7 +236,7 @@ rec {
        => { right = [ 5 3 4 ]; wrong = [ 1 2 ]; }
   */
   partition = builtins.partition or (pred:
-    fold (h: t:
+    foldr (h: t:
       if pred h
       then { right = [h] ++ t.right; wrong = t.wrong; }
       else { right = t.right; wrong = [h] ++ t.wrong; }