Nix Functions Explained

2025-05-05

Nix Functions

Functions are all over Nix Code and an important concept to grasp to start understanding Nix.

In Nix, all functions conceptually take exactly one argument. Multi-argument functions are done through a series of nested single-argument functions (currying).

Argument and function body are separated by a colon (:).

Wherever you find a colon (:) in Nix code:

For example:

greet = personName: "Hello, ${personName}!"
greet "Anonymous"   # Evaluates to "Hello, Anonymous!"

Function Declarations

inc = x: x + 1
inc 5  # Evaluates to 6
concat = x: y: x + y
concat 6 6   # Evaluates to 12
greeting = prefix: name: "${prefix}, ${name}!";

Think of this as a chain of single-argument functions:

  1. Outer Function: prefix: (name: "${prefix}, ${name}!")
  1. Inner Function: name: "${prefix}, ${name}!"

Step-by-Step Evaluation of this Multi-Argument Call:

When you write greeting "Hello" "Alice", Nix evaluates it like this:

  1. greeting "Hello"
  1. (greeting "Hello") "Alice":

Every colon you see in a function definition separates a single argument (on its left) from its corresponding function body (on its right). Even when the body is another function definition.

Partial Application

Because Nix functions are curried, you can apply arguments one at a time. This is known as partial application. When you apply a function to some, but not all, of its expected arguments, you get a new function that "remembers" the arguments you've already provided and is waiting for the remaining ones.

Revisiting our greeting function:

greeting = prefix: name: "${prefix}, ${name}!";

If we only provide the prefix:

helloGreeting = greeting "Hello";
helloGreeting "Sally"  # Evaluates to "Hello, Sally!"

Most NixOS and home-manager modules are actually functions

It's important to recognize that the function paradigm is central to how NixOS and Home Manager modules are structured. Most NixOS and Home Manager modules are fundamentally functions.

For example, a simplified service module could be:

{ config, lib, pkgs, ... }: {
  services.nginx.enable = true;
  services.nginx.package = pkgs.nginx;
  services.nginx.settings.http-port = "8080";
}

Resources