nixpkgs-lib.md

nixpkgs lib

Before this, you'll want

  1. Builtin functions
The Nix language15 min

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:

nix replevaluated as you typeambient libA piece of a larger file. `lib` was bound by the part not shown, so it is supplied here too.

Take part of a list

lib.take keeps values from the beginning. lib.drop skips values from the beginning:

nix replevaluated as you typeambient libA piece of a larger file. `lib` was bound by the part not shown, so it is supplied here too.

Try changing both 2s. The original list stays unchanged.

Remove repeated values

lib.unique keeps the first copy of each value:

Try it

Remove the repeats and keep git, vim, then htop.

nix replevaluated as you typeambient libA piece of a larger file. `lib` was bound by the part not shown, so it is supplied here too.

Join strings

lib.concatStringsSep joins a list of strings and places a separator between them:

Try it

Join the computer parts into "CPU + RAM + SSD".

nix replevaluated as you typeambient libA piece of a larger file. `lib` was bound by the part not shown, so it is supplied here too.

Ask how a string begins or ends

lib.hasPrefix and lib.hasSuffix answer yes or no about the edges of a string. Sorting filenames is where you’ll meet them most:

nix replevaluated as you typeambient libA piece of a larger file. `lib` was bound by the part not shown, so it is supplied here too.

The thing being looked for comes first, and the string being asked about second.

Ask about a whole list

lib.any returns true when at least one value passes a function:

nix replevaluated as you typeambient libA piece of a larger file. `lib` was bound by the part not shown, so it is supplied here too.

Change any to all and see how the question changes.

Transform every attribute

lib.mapAttrs calls a function with each attribute name and value. It keeps the names and replaces the values with the results:

nix replevaluated as you typeambient libA piece of a larger file. `lib` was bound by the part not shown, so it is supplied here too.

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:

Try it

Label each measurement with its own name, so height reads "height:35".

nix replevaluated as you typeambient libA piece of a larger file. `lib` was bound by the part not shown, so it is supplied here too.

toString is there because + joins a string to a string, and a measurement is a number.

Add a value only when needed

lib.optional produces a one-item list when its condition is true, or an empty list when it is false:

nix replevaluated as you typeambient libA piece of a larger file. `lib` was bound by the part not shown, so it is supplied here too.

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.

Try it

Bring both debugging tools in, and keep the result one flat list.

nix replevaluated as you typeambient libA piece of a larger file. `lib` was bound by the part not shown, so it is supplied here too.

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.

Helpers are grouped too

Common helpers are available directly as lib.take, but nixpkgs also groups them by topic. These two expressions call the same function:

nix replevaluated as you typeambient libA piece of a larger file. `lib` was bound by the part not shown, so it is supplied here too.

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.

Build a lib function yourself

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:

nix replevaluated as you typeambient libA piece of a larger file. `lib` was bound by the part not shown, so it is supplied here too.

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.

The library is Nix code too

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.

What to keep

  • builtins provides the small toolbox implemented by the Nix evaluator.
  • lib provides a larger toolbox shipped as readable Nix code in nixpkgs.
  • List helpers include take, drop, unique, any, and all.
  • String helpers include concatStringsSep, hasPrefix, and hasSuffix.
  • Attribute-set helpers such as mapAttrs transform values, and hand you the name too.
  • optional adds one value on a condition. optionals adds 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.

Useful links

NORMALCOURSE IN BETA