diff options
author | Eelco Dolstra <eelco.dolstra@logicblox.com> | 2009-02-09 16:51:03 +0000 |
---|---|---|
committer | Eelco Dolstra <eelco.dolstra@logicblox.com> | 2009-02-09 16:51:03 +0000 |
commit | 599015e8b071bc8d38779fbfc37961db1ac0f464 (patch) | |
tree | 12cfb8ef316f4021ef81d135a5c331804a817809 /pkgs/lib/lists.nix | |
parent | eebb6f106c445c5661975a60a55b07ad91c6fa47 (diff) | |
download | nixpkgs-599015e8b071bc8d38779fbfc37961db1ac0f464.tar nixpkgs-599015e8b071bc8d38779fbfc37961db1ac0f464.tar.gz nixpkgs-599015e8b071bc8d38779fbfc37961db1ac0f464.tar.bz2 nixpkgs-599015e8b071bc8d38779fbfc37961db1ac0f464.tar.lz nixpkgs-599015e8b071bc8d38779fbfc37961db1ac0f464.tar.xz nixpkgs-599015e8b071bc8d38779fbfc37961db1ac0f464.tar.zst nixpkgs-599015e8b071bc8d38779fbfc37961db1ac0f464.zip |
* Split lib/default.nix into several files, as it had become a big
mess. Also cleaned up some functions: - foldl appeared broken (it recursively called fold). - Renamed logicalAND/logicalOR to and/or. - Removed listOfListsToAttrs, eqStrings: obsolete. - Removed isInList, which does the same thing as elem. - stringToCharacters: don't return a "" at the end of the list. - Renamed concatList to concat, as concatList (singular) is a misnomer: it takes two lists. Likewise, renamed mergeAttr to mergeAttrs. misc.nix still contains a lot of stuff that should be refactored and moved to other files. svn path=/nixpkgs/trunk/; revision=14013
Diffstat (limited to 'pkgs/lib/lists.nix')
-rw-r--r-- | pkgs/lib/lists.nix | 118 |
1 files changed, 118 insertions, 0 deletions
diff --git a/pkgs/lib/lists.nix b/pkgs/lib/lists.nix new file mode 100644 index 00000000000..b186e97a55b --- /dev/null +++ b/pkgs/lib/lists.nix @@ -0,0 +1,118 @@ +# General list operations. + +rec { + inherit (builtins) head tail isList; + + + # "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). + fold = op: nul: list: + if list == [] + then nul + else op (head list) (fold op nul (tail list)); + + + # Left fold: `fold op nul [x_1 x_2 ... x_n] == op (... (op (op nul + # x_1) x_2) ... x_n)'. + foldl = op: nul: list: + if list == [] + then nul + else foldl op (op nul (head list)) (tail list); + + + # Concatenate a list of lists. + concatLists = fold (x: y: x ++ y) []; + + + # Map and concatenate the result. + concatMap = f: list: concatLists (map f list); + + + # Flatten the argument into a single list; that is, nested lists are + # spliced into the top-level lists. E.g., `flatten [1 [2 [3] 4] 5] + # == [1 2 3 4 5]' and `flatten 1 == [1]'. + flatten = x: + if isList x + then fold (x: y: (flatten x) ++ y) [] x + else [x]; + + + # Filter a list using a predicate; that is, return a list containing + # every element from `list' for which `pred' returns true. + filter = pred: list: + fold (x: y: if pred x then [x] ++ y else y) [] list; + + + # Return true if `list' has an element `x': + elem = x: list: fold (a: bs: x == a || bs) false list; + + + # Find the sole element in the list matching the specified + # predicate, returns `default' if no such element exists, or + # `multiple' if there are multiple matching elements. + findSingle = pred: default: multiple: list: + let found = filter pred list; + in if found == [] then default + else if tail found != [] then multiple + else head found; + + + # Return true iff function `pred' returns true for at least element + # of `list'. + any = pred: list: + if list == [] then false + else if pred (head list) then true + else any pred (tail list); + + + # Return true iff function `pred' returns true for all elements of + # `list'. + all = pred: list: + if list == [] then true + else if pred (head list) then all pred (tail list) + else false; + + + # Return true if each element of a list is equal, false otherwise. + eqLists = xs: ys: + if xs == [] && ys == [] then true + else if xs == [] || ys == [] then false + else head xs == head ys && eqLists (tail xs) (tail ys); + + + # Return a singleton list or an empty list, depending on a boolean + # value. Useful when building lists with optional elements + # (e.g. `++ optional (system == "i686-linux") flashplayer'). + optional = cond: elem: if cond then [elem] else []; + + + # Return a list or an empty list, dependening on a boolean value. + optionals = cond: elems: if cond then elems else []; + + + # If argument is a list, return it; else, wrap it in a singleton + # list. If you're using this, you should almost certainly + # reconsider if there isn't a more "well-typed" approach. + toList = x: if builtins.isList x then x else [x]; + + + # Return a list of integers from `first' up to and including `last'. + range = first: last: + if builtins.lessThan last first + then [] + else [first] ++ range (builtins.add first 1) last; + + + # Partition the elements of a list in two lists, `right' and + # `wrong', depending on the evaluation of a predicate. + partition = pred: + fold (h: t: + if pred h + then { right = [h] ++ t.right; wrong = t.wrong; } + else { right = t.right; wrong = [h] ++ t.wrong; } + ) { right = []; wrong = []; }; + + +} |