Builtins gave you the essentials, and they run out fast.
lib is what nixpkgs adds on top: practical
functions that exist because somebody already wrote the
one you were about to write. Nix hates repetition, and lib is the
ecosystem taking that personally.
Every playground below has a slice of it loaded, so change the code and watch:
lib.take keeps values from the beginning. lib.drop skips values from the
beginning:
Try changing both 2s. The original list stays unchanged.
lib.unique keeps the first copy of each value:
Remove the repeats and keep git, vim, then htop.
lib.concatStringsSep joins a list of strings and places a separator between
them:
Join the computer parts into "CPU + RAM + SSD".
lib.hasPrefix and lib.hasSuffix answer yes or no about the edges of a
string. Sorting filenames is where you’ll meet them most:
The thing being looked for comes first, and the string being asked about second.
lib.any returns true when at least one value passes a function:
Change any to all and see how the question changes.
lib.mapAttrs calls a function with each
attribute name and value. It keeps the names and
replaces the values with the results:
mapAttrs passes the name first and the value second. This one has no use for
name, and doubles pixels.
That first argument is the whole reason to reach for mapAttrs instead of
transforming the values some other way. Take it, and the name is yours to use:
Label each measurement with its own name, so height reads "height:35".
toString is there because + joins a string to a string, and a measurement is
a number.
lib.optional produces a one-item list when its condition is true, or an empty
list when it is false:
This is handy when building a list from several conditions.
The one you will actually type more often is its plural. lib.optionals takes a
whole list rather than a single value, which is what you want the moment one
condition brings more than one thing along with it.
Bring both debugging tools in, and keep the result one flat list.
And look at what the singular one handed you first: a list holding a list, which
++ was perfectly happy to join on without a word. One letter is the entire
difference between the two.
Common helpers are available directly as lib.take, but nixpkgs also groups
them by topic. These two expressions call the same function:
The playground includes a curated set of common list, string, and attribute-set helpers. It does not pretend to contain every function in the enormous library.
Here is the complete idea behind lib.optional. It takes a condition, then a
value. It returns a one-item list when the condition is true and an empty list
otherwise:
That is more or less exactly how nixpkgs writes it. Change wantsDebugger,
change the value, or rename the function. Nothing here needs special evaluator
magic. It is a function written out of concepts you already know.
Builtins are implemented by the Nix evaluator. Their implementation lives underneath the language, so a Nix file can call them but cannot open their Nix source.
Nixpkgs lib is different. The library is shipped as ordinary, readable Nix
source in the nixpkgs repository. Its functions combine, wrap, and sometimes
re-export builtins to create a larger toolbox.
Open the pinned list helpers source
and search for optional or take.
The helpers may be clever, but there is no secret compiler spell inside them.
They are Nix expressions you can read, learn from, and even recreate yourself.
That is the trick. A small language can grow a huge toolbox when the toolbox is written in the language itself.
builtinsprovides the small toolbox implemented by the Nix evaluator.libprovides a larger toolbox shipped as readable Nix code in nixpkgs.- List helpers include
take,drop,unique,any, andall. - String helpers include
concatStringsSep,hasPrefix, andhasSuffix. - Attribute-set helpers such as
mapAttrstransform values, and hand you the name too. optionaladds one value on a condition.optionalsadds a whole list.
You don’t need to memorize the library. It’s ordinary Nix code, so hover common helpers for friendly examples and reach for it when a small builtin isn’t enough for the job.
Later, you’ll use another side of lib to assemble entire system
configurations. We’ll open that toolbox when we reach modules.


Share your thoughts