5 ## Simple (higher order) functions
7 /* The identity function
8 For when you need a function that does “nothing”.
16 /* The constant function
18 Ignores the second argument. If called with only one argument,
19 constructs a function that always returns a static value.
21 Type: const :: a -> b -> a
23 let f = const 5; in f 10
32 /* Pipes a value through a list of functions, left to right.
34 Type: pipe :: a -> [<functions>] -> <return type of last function>
37 (x: x + 2) # 2 + 2 = 4
38 (x: x * 2) # 4 * 2 = 8
42 # ideal to do text transformations
43 pipe [ "a/b" "a/c" ] [
45 # create the cp command
46 (map (file: ''cp "${src}/${file}" $out\n''))
48 # concatenate all commands into one string
51 # make that string into a nix derivation
52 (pkgs.runCommand "copy-to-out" {})
55 => <drv which copies all files to $out>
57 The output type of each function has to be the input type
58 of the next function, and the last function returns the
61 pipe = val: functions:
62 let reverseApply = x: f: f x;
63 in builtins.foldl' reverseApply val functions;
65 # note please don’t add a function like `compose = flip pipe`.
66 # This would confuse users, because the order of the functions
67 # in the list is not clear. With pipe, it’s obvious that it
68 # goes first-to-last. With `compose`, not so much.
70 ## Named versions corresponding to some builtin operators.
72 /* Concatenate two lists
74 Type: concat :: [a] -> [a] -> [a]
77 concat [ 1 2 ] [ 3 4 ]
80 concat = x: y: x ++ y;
89 bitAnd = builtins.bitAnd
90 or (import ./zip-int-bits.nix
91 (a: b: if a==1 && b==1 then 1 else 0));
94 bitOr = builtins.bitOr
95 or (import ./zip-int-bits.nix
96 (a: b: if a==1 || b==1 then 1 else 0));
99 bitXor = builtins.bitXor
100 or (import ./zip-int-bits.nix
101 (a: b: if a!=b then 1 else 0));
104 bitNot = builtins.sub (-1);
106 /* Convert a boolean to a string.
108 This function uses the strings "true" and "false" to represent
109 boolean values. Calling `toString` on a bool instead returns "1"
112 Type: boolToString :: bool -> string
114 boolToString = b: if b then "true" else "false";
116 /* Merge two attribute sets shallowly, right side trumps left
118 mergeAttrs :: attrs -> attrs -> attrs
121 mergeAttrs { a = 1; b = 2; } { b = 3; c = 4; }
122 => { a = 1; b = 3; c = 4; }
127 # Right attribute set (higher precedence for equal keys)
130 /* Flip the order of the arguments of a binary function.
132 Type: flip :: (a -> b -> c) -> (b -> a -> c)
138 flip = f: a: b: f b a;
140 /* Apply function if the supplied argument is non-null.
143 mapNullable (x: x+1) null
145 mapNullable (x: x+1) 22
151 # Argument to check for null before passing it to `f`
152 a: if a == null then a else f a;
154 # Pull in some builtins not included elsewhere.
156 pathExists readFile isBool
157 isInt isFloat add sub lessThan
158 seq deepSeq genericClosure;
161 ## nixpkgs version strings
163 /* Returns the current full nixpkgs version number. */
164 version = release + versionSuffix;
166 /* Returns the current nixpkgs release number as string. */
167 release = lib.strings.fileContents ../.version;
169 /* The latest release that is supported, at the time of release branch-off,
172 Ideally, out-of-tree modules should be able to evaluate cleanly with all
173 supported Nixpkgs versions (master, release and old release until EOL).
174 So if possible, deprecation warnings should take effect only when all
175 out-of-tree expressions/libs/modules can upgrade to the new way without
176 losing support for supported Nixpkgs versions.
178 This release number allows deprecation warnings to be implemented such that
179 they take effect as soon as the oldest release reaches end of life. */
180 oldestSupportedRelease =
181 # Update on master only. Do not backport.
184 /* Whether a feature is supported in all supported releases (at the time of
185 release branch-off, if applicable). See `oldestSupportedRelease`. */
187 /* Release number of feature introduction as an integer, e.g. 2111 for 21.11.
188 Set it to the upcoming release, matching the nixpkgs/.version file.
191 release <= lib.trivial.oldestSupportedRelease;
193 /* Returns the current nixpkgs release code name.
195 On each release the first letter is bumped and a new animal is chosen
196 starting with that new letter.
200 /* Returns the current nixpkgs version suffix as string. */
202 let suffixFile = ../.version-suffix;
203 in if pathExists suffixFile
204 then lib.strings.fileContents suffixFile
207 /* Attempts to return the the current revision of nixpkgs and
208 returns the supplied default value otherwise.
210 Type: revisionWithDefault :: string -> string
212 revisionWithDefault =
213 # Default value to return if revision can not be determined
216 revisionFile = "${toString ./..}/.git-revision";
217 gitRepo = "${toString ./..}/.git";
218 in if lib.pathIsGitRepo gitRepo
219 then lib.commitIdFromGitRepo gitRepo
220 else if lib.pathExists revisionFile then lib.fileContents revisionFile
223 nixpkgsVersion = builtins.trace "`lib.nixpkgsVersion` is deprecated, use `lib.version` instead!" version;
225 /* Determine whether the function is being called from inside a Nix
228 Type: inNixShell :: bool
230 inNixShell = builtins.getEnv "IN_NIX_SHELL" != "";
232 /* Determine whether the function is being called from inside pure-eval mode
233 by seeing whether `builtins` contains `currentSystem`. If not, we must be in
236 Type: inPureEvalMode :: bool
238 inPureEvalMode = ! builtins ? currentSystem;
240 ## Integer operations
242 /* Return minimum of two numbers. */
243 min = x: y: if x < y then x else y;
245 /* Return maximum of two numbers. */
246 max = x: y: if x > y then x else y;
256 mod = base: int: base - (int * (builtins.div base int));
261 /* C-style comparisons
263 a < b, compare a b => -1
264 a == b, compare a b => 0
265 a > b, compare a b => 1
274 /* Split type into two subtypes by predicate `p`, take all elements
275 of the first subtype to be less than all the elements of the
276 second subtype, compare elements of a single subtype with `yes`
277 and `no` respectively.
279 Type: (a -> bool) -> (a -> a -> int) -> (a -> a -> int) -> (a -> a -> int)
282 let cmp = splitByAndCompare (hasPrefix "foo") compare compare; in
285 cmp "fooa" "fooz" => -1
290 compare "fooa" "a" => 1
295 # Comparison function if predicate holds for both values
297 # Comparison function if predicate holds for neither value
299 # First value to compare
301 # Second value to compare
304 then if p b then yes a b else -1
305 else if p b then 1 else no a b;
308 /* Reads a JSON file.
310 Type: importJSON :: path -> any
313 builtins.fromJSON (builtins.readFile path);
315 /* Reads a TOML file.
317 Type: importTOML :: path -> any
320 builtins.fromTOML (builtins.readFile path);
324 # See https://github.com/NixOS/nix/issues/749. Eventually we'd like these
325 # to expand to Nix builtins that carry metadata so that Nix can filter out
326 # the INFO messages without parsing the message string.
330 # foo = lib.warn "foo is deprecated" oldFoo;
331 # bar = lib.warnIf (bar == "") "Empty bar is deprecated" bar;
334 # TODO: figure out a clever way to integrate location information from
335 # something like __unsafeGetAttrPos.
338 Print a warning before returning the second argument. This function behaves
339 like `builtins.trace`, but requires a string message and formats it as a
340 warning, including the `warning: ` prefix.
342 To get a call stack trace and abort evaluation, set the environment variable
343 `NIX_ABORT_ON_WARN=true` and set the Nix options `--option pure-eval false --show-trace`
345 Type: string -> a -> a
348 if lib.elem (builtins.getEnv "NIX_ABORT_ON_WARN") ["1" "true" "yes"]
349 then msg: builtins.trace "
\e[1;31mwarning: ${msg}
\e[0m" (abort "NIX_ABORT_ON_WARN=true; warnings are treated as unrecoverable errors.")
350 else msg: builtins.trace "
\e[1;31mwarning: ${msg}
\e[0m";
353 Like warn, but only warn when the first argument is `true`.
355 Type: bool -> string -> a -> a
357 warnIf = cond: msg: if cond then warn msg else x: x;
360 Like warnIf, but negated (warn if the first argument is `false`).
362 Type: bool -> string -> a -> a
364 warnIfNot = cond: msg: if cond then x: x else warn msg;
367 Like the `assert b; e` expression, but with a custom error message and
368 without the semicolon.
370 If true, return the identity function, `r: r`.
372 If false, throw the error message.
374 Calls can be juxtaposed using function application, as `(r: r) a = a`, so
375 `(r: r) (r: r) a = a`, and so forth.
377 Type: bool -> string -> a -> a
381 throwIfNot (lib.isList overlays) "The overlays argument to nixpkgs must be a list."
382 lib.foldr (x: throwIfNot (lib.isFunction x) "All overlays passed to nixpkgs must be functions.") (r: r) overlays
386 throwIfNot = cond: msg: if cond then x: x else throw msg;
389 Like throwIfNot, but negated (throw if the first argument is `true`).
391 Type: bool -> string -> a -> a
393 throwIf = cond: msg: if cond then throw msg else x: x;
395 /* Check if the elements in a list are valid values from a enum, returning the identity function, or throwing an error message otherwise.
398 let colorVariants = ["bright" "dark" "black"]
399 in checkListOfEnum "color variants" [ "standard" "light" "dark" ] colorVariants;
401 error: color variants: bright, black unexpected; valid ones: standard, light, dark
403 Type: String -> List ComparableVal -> List ComparableVal -> a -> a
405 checkListOfEnum = msg: valid: given:
407 unexpected = lib.subtractLists valid given;
409 lib.throwIfNot (unexpected == [])
410 "${msg}: ${builtins.concatStringsSep ", " (builtins.map builtins.toString unexpected)} unexpected; valid ones: ${builtins.concatStringsSep ", " (builtins.map builtins.toString valid)}";
412 info = msg: builtins.trace "INFO: ${msg}";
414 showWarnings = warnings: res: lib.foldr (w: x: warn w x) res warnings;
416 ## Function annotations
418 /* Add metadata about expected function arguments to a function.
419 The metadata should match the format given by
420 builtins.functionArgs, i.e. a set from expected argument to a bool
421 representing whether that argument has a default or not.
422 setFunctionArgs : (a → b) → Map String Bool → (a → b)
424 This function is necessary because you can't dynamically create a
425 function of the { a, b ? foo, ... }: format, but some facilities
426 like callPackage expect to be able to query expected arguments.
428 setFunctionArgs = f: args:
429 { # TODO: Should we add call-time "type" checking like built in?
431 __functionArgs = args;
434 /* Extract the expected function arguments from a function.
435 This works both with nix-native { a, b ? foo, ... }: style
436 functions and functions with args set with 'setFunctionArgs'. It
437 has the same return type and semantics as builtins.functionArgs.
438 setFunctionArgs : (a → b) → Map String Bool.
442 then f.__functionArgs or (lib.functionArgs (f.__functor f))
443 else builtins.functionArgs f;
445 /* Check whether something is a function or something
446 annotated with function args.
448 isFunction = f: builtins.isFunction f ||
449 (f ? __functor && isFunction (f.__functor f));
452 Turns any non-callable values into constant functions.
453 Returns callable values as is.
457 nix-repl> lib.toFunction 1 2
460 nix-repl> lib.toFunction (x: x + 1) 2
470 /* Convert the given positive integer to a string of its hexadecimal
471 representation. For example:
475 toHexString 16 => "10"
477 toHexString 250 => "FA"
494 lib.concatMapStrings toHexDigit (toBaseDigits 16 i);
496 /* `toBaseDigits base i` converts the positive integer i to a list of its
497 digits in the given base. For example:
499 toBaseDigits 10 123 => [ 1 2 3 ]
501 toBaseDigits 2 6 => [ 1 1 0 ]
503 toBaseDigits 16 250 => [ 15 10 ]
505 toBaseDigits = base: i:
512 r = i - ((i / base) * base);
521 lib.reverseList (go i);