Nix Language Basics

Nix configuration is not only a collection of package names. Underneath it is a small expression language used to build values, combine them, and describe build tasks.

That language matters because shells, packages, flakes, and system configuration eventually become Nix expressions.

Core Shape

The Nix language is functional and lazy. Functional means expressions produce values and functions are ordinary tools for transforming data. Lazy means expressions are not fully evaluated until their values are needed.

The basic ingredients are:

Ingredient Role
Primitive values Simple values such as numbers, strings, booleans, and paths.
Compound values Lists and attribute sets that group values.
Functions and operators Ways to transform or combine values.
Name bindings Assign names so values can be reused as units.
Derivations Descriptions of build tasks that Nix can realize into outputs.

A derivation is the bridge between language and build system: it is data that says how to produce something.

Trying Expressions

The REPL is the smallest feedback loop:

nix repl

Inside it, simple expressions can be evaluated immediately:

nix-repl> 1 + 2
2

A Nix expression can also be written in a file and evaluated from the command line:

nix-instantiate --eval --strict file.nix

The --eval flag asks Nix to evaluate the expression. The --strict flag forces lazy structures to be expanded enough to inspect the result.

Why Laziness Shows Up

Laziness is useful because large Nix configurations may define many possible values while only needing some of them for a particular command. It can also surprise beginners because a broken expression may not fail until something demands that value.

When debugging, make evaluation explicit. Use the REPL or strict evaluation to move from a large configuration to a small expression you can inspect.