1{ lib }:
2
3rec {
4
5 ## Simple (higher order) functions
6
7 /* The identity function
8 For when you need a function that does “nothing”.
9
10 Type: id :: a -> a
11 */
12 id = x: x;
13
14 /* The constant function
15 Ignores the second argument.
16 Or: Construct a function that always returns a static value.
17
18 Type: const :: a -> b -> a
19 Example:
20 let f = const 5; in f 10
21 => 5
22 */
23 const = x: y: x;
24
25
26 ## Named versions corresponding to some builtin operators.
27
28 /* Concatenate two lists */
29 concat = x: y: x ++ y;
30
31 /* boolean “or” */
32 or = x: y: x || y;
33
34 /* boolean “and” */
35 and = x: y: x && y;
36
37 /* bitwise “and” */
38 bitAnd = builtins.bitAnd
39 or import ./zip-int-bits.nix
40 (a: b: if a==1 && b==1 then 1 else 0);
41
42 /* bitwise “or” */
43 bitOr = builtins.bitOr
44 or import ./zip-int-bits.nix
45 (a: b: if a==1 || b==1 then 1 else 0);
46
47 /* bitwise “xor” */
48 bitXor = builtins.bitXor
49 or import ./zip-int-bits.nix
50 (a: b: if a!=b then 1 else 0);
51
52 /* bitwise “not” */
53 bitNot = builtins.sub (-1);
54
55 /* Convert a boolean to a string.
56 Note that toString on a bool returns "1" and "".
57 */
58 boolToString = b: if b then "true" else "false";
59
60 /* Merge two attribute sets shallowly, right side trumps left
61
62 Example:
63 mergeAttrs { a = 1; b = 2; } { b = 3; c = 4; }
64 => { a = 1; b = 3; c = 4; }
65 */
66 mergeAttrs = x: y: x // y;
67
68 /* Flip the order of the arguments of a binary function.
69
70 Example:
71 flip concat [1] [2]
72 => [ 2 1 ]
73 */
74 flip = f: a: b: f b a;
75
76 /* Apply function if argument is non-null.
77
78 Example:
79 mapNullable (x: x+1) null
80 => null
81 mapNullable (x: x+1) 22
82 => 23
83 */
84 mapNullable = f: a: if isNull a then a else f a;
85
86 # Pull in some builtins not included elsewhere.
87 inherit (builtins)
88 pathExists readFile isBool
89 isInt isFloat add sub lessThan
90 seq deepSeq genericClosure;
91
92
93 ## nixpks version strings
94
95 # The current full nixpkgs version number.
96 version = release + versionSuffix;
97
98 # The current nixpkgs version number as string.
99 release = lib.strings.fileContents ../.version;
100
101 # The current nixpkgs version suffix as string.
102 versionSuffix =
103 let suffixFile = ../.version-suffix;
104 in if pathExists suffixFile
105 then lib.strings.fileContents suffixFile
106 else "pre-git";
107
108 nixpkgsVersion = builtins.trace "`lib.nixpkgsVersion` is deprecated, use `lib.version` instead!" version;
109
110 # Whether we're being called by nix-shell.
111 inNixShell = builtins.getEnv "IN_NIX_SHELL" != "";
112
113
114 ## Integer operations
115
116 # Return minimum/maximum of two numbers.
117 min = x: y: if x < y then x else y;
118 max = x: y: if x > y then x else y;
119
120 /* Integer modulus
121
122 Example:
123 mod 11 10
124 => 1
125 mod 1 10
126 => 1
127 */
128 mod = base: int: base - (int * (builtins.div base int));
129
130
131 ## Comparisons
132
133 /* C-style comparisons
134
135 a < b, compare a b => -1
136 a == b, compare a b => 0
137 a > b, compare a b => 1
138 */
139 compare = a: b:
140 if a < b
141 then -1
142 else if a > b
143 then 1
144 else 0;
145
146 /* Split type into two subtypes by predicate `p`, take all elements
147 of the first subtype to be less than all the elements of the
148 second subtype, compare elements of a single subtype with `yes`
149 and `no` respectively.
150
151 Example:
152
153 let cmp = splitByAndCompare (hasPrefix "foo") compare compare; in
154
155 cmp "a" "z" => -1
156 cmp "fooa" "fooz" => -1
157
158 cmp "f" "a" => 1
159 cmp "fooa" "a" => -1
160 # while
161 compare "fooa" "a" => 1
162 */
163 splitByAndCompare = p: yes: no: a: b:
164 if p a
165 then if p b then yes a b else -1
166 else if p b then 1 else no a b;
167
168
169 /* Reads a JSON file. */
170 importJSON = path:
171 builtins.fromJSON (builtins.readFile path);
172
173
174 ## Warnings and asserts
175
176 /* See https://github.com/NixOS/nix/issues/749. Eventually we'd like these
177 to expand to Nix builtins that carry metadata so that Nix can filter out
178 the INFO messages without parsing the message string.
179
180 Usage:
181 {
182 foo = lib.warn "foo is deprecated" oldFoo;
183 }
184
185 TODO: figure out a clever way to integrate location information from
186 something like __unsafeGetAttrPos.
187 */
188 warn = msg: builtins.trace "WARNING: ${msg}";
189 info = msg: builtins.trace "INFO: ${msg}";
190
191
192 ## Function annotations
193
194 /* Add metadata about expected function arguments to a function.
195 The metadata should match the format given by
196 builtins.functionArgs, i.e. a set from expected argument to a bool
197 representing whether that argument has a default or not.
198 setFunctionArgs : (a → b) → Map String Bool → (a → b)
199
200 This function is necessary because you can't dynamically create a
201 function of the { a, b ? foo, ... }: format, but some facilities
202 like callPackage expect to be able to query expected arguments.
203 */
204 setFunctionArgs = f: args:
205 { # TODO: Should we add call-time "type" checking like built in?
206 __functor = self: f;
207 __functionArgs = args;
208 };
209
210 /* Extract the expected function arguments from a function.
211 This works both with nix-native { a, b ? foo, ... }: style
212 functions and functions with args set with 'setFunctionArgs'. It
213 has the same return type and semantics as builtins.functionArgs.
214 setFunctionArgs : (a → b) → Map String Bool.
215 */
216 functionArgs = f: f.__functionArgs or (builtins.functionArgs f);
217
218 /* Check whether something is a function or something
219 annotated with function args.
220 */
221 isFunction = f: builtins.isFunction f ||
222 (f ? __functor && isFunction (f.__functor f));
223}