nixpkgs-suyu/pkgs/lib/default.nix
Eelco Dolstra c5e1ae5eaf * Purity fix in building Python: don't let it search in /usr/include
and /usr/lib to determine what optional modules (like bzip2, zlib,
  dl, etc.) to build.  Unfortunately there doesn't seem to be a way to
  tell the Python build process to look anywhere else, so I had to
  patch setup.py.

svn path=/nixpkgs/trunk/; revision=8780
2007-05-27 14:34:01 +00:00

121 lines
3.5 KiB
Nix

# Utility functions.
let
inherit (builtins)
head tail isList stringLength substring lessThan sub;
in
rec {
# "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));
# Concatenate a list of lists.
concatLists =
fold (x: y: x ++ y) [];
# Concatenate a list of strings.
concatStrings =
fold (x: y: x + y) "";
# Place an element between each element of a list, e.g.,
# `intersperse "," ["a" "b" "c"]' returns ["a" "," "b" "," "c"].
intersperse = separator: list:
if list == [] || tail list == []
then list
else [(head list) separator]
++ (intersperse separator (tail list));
concatStringsSep = separator: list:
concatStrings (intersperse separator 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];
# Return an attribute from nested attribute sets. For instance ["x"
# "y"] applied to some set e returns e.x.y, if it exists. The
# default value is returned otherwise.
getAttr = attrPath: default: e:
let {
attr = head attrPath;
body =
if attrPath == [] then e
else if builtins ? hasAttr && builtins.hasAttr attr e
then getAttr (tail attrPath) default (builtins.getAttr attr e)
else default;
};
# 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, or returns the default value.
findSingle = pred: default: list:
let found = filter pred list;
in if found == [] then default
else if tail found != [] then
abort "Multiple elements match predicate in findSingle."
else head found;
# 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);
# Determine whether a filename ends in the given suffix.
hasSuffix = ext: fileName:
let lenFileName = stringLength fileName;
lenExt = stringLength ext;
in !(lessThan lenFileName lenExt) &&
substring (sub lenFileName lenExt) lenFileName fileName == ext;
# Bring in a path as a source, filtering out all Subversion and CVS
# directories, as well as backup files (*~).
cleanSource =
let filter = name: type: let baseName = baseNameOf (toString name); in ! (
# Filter out Subversion and CVS directories.
(type == "directory" && (name == ".svn" || name == "CVS")) ||
# Filter out backup files.
(hasSuffix "~" name)
);
in src: builtins.filterSource filter src;
# 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 [];
}