tracking for shynet analytics when Javascript is disabled Conditionally add values into list or map in Nix — Hugo Sum
Hugo Sum

Conditionally add values into list or map in Nix

I often find myself conditionally adding values into a list or map when writing configurations and derivations in Nix. In this post I want to show you how to conditionally add values into list or map in Nix.

Similar to many other functional languages, all values are immutable, and no statement exists in Nix. Instead of relying on method such as push() that would mutate an object, you have to use composition to add values into a list or map.

Conditionally add values into a list in Nix

To conditionally add values into a list in Nix, we can use the list concatenation operator ++ together with a if expression. Remember if in Nix is an expression instead of statement, therefore it can return value. The following example shows you how to add c and d into the list of foo, if acceptAdditional is true.

example.nix
let
   acceptAdditional = true;
in {
  foo = [ "a" "b" ] ++
    (if config.bar.enable then [ "c" "d" ] else [ ]);
}

If we evaluate the above file with nix repl, we can see that the value of foo evaluated to the combination of foo and bar.

 nix repl --file example.nix
Welcome to Nix 2.18.1. Type :? for help.

Loading installable ''...
Added 1 variables.
nix-repl> foo
[ "a" "b" "c" "d" ]

We can simplify our code with the helper function lib.lists.optionals for the same effect, where an empty list will be returned, if the condition is not true.

example.nix
let
   acceptAdditional = true;
in {
  foo = [ "a" "b" ] ++
    (if acceptAdditional then [ "c" "d" ] else [ ]);
    (lib.lists.optionals acceptAdditional [ "c" "d" ]);
}

Conditionally add values into a map in Nix

To conditionally add values into a map in Nix, we can use the Update operator //. The attributes of the map in the right-hand side of the operator, will be merged into the map in the left-hand side.

example.nix
let
    acceptAdditional = true;
in {
  foo = {
    a = "d";
    b = "e";
  } // (if acceptAdditional then {
    one = "1";
    two = "2";
  } else
    { });
}

By evaluating it, we can see that attribute one and two is now merged into foo.

 nix repl --file example.nix
Welcome to Nix 2.18.1. Type :? for help.

Loading installable ''...
Added 1 variables.
nix-repl> foo
{ a = "d"; b = "e"; one = "1"; two = "2"; }

If any attribute on the right-hand side’s map is identical with the left-hand side’s map, it will overwrite its value. This is really useful for conditionally setting value of attributes in a map.

example.nix
let
    acceptAdditional = true;
in {
  foo = {
    a = "d";
    b = "e";
  } // (if acceptAdditional then {
    one = "1";
    two = "2";
    a = "new value";
  } else
    { });
}

As you can see, the value of a has been overwritten into the value of the same attribute of the right-hand side map.

 nix repl --file example.nix
Welcome to Nix 2.18.1. Type :? for help.

Loading installable ''...
Added 1 variables.
nix-repl> foo
{ a = "new value"; b = "e"; one = "1"; two = "2"; }

To simplify our code and avoid writing if expression, we can use the helper function lib.attrsets.optionalAttrs.

example.nix
let
    acceptAdditional = true;
in {
  foo = {
    a = "d";
    b = "e";
  } // (lib.attrsets.optionalAttrs acceptAdditional {
    one = "1";
    two = "2";
    a = "new value";
  });
}

The limitation for \\ operator is that it cannot merge recursively. If you want a recursive merge, you can use the helper function lib.attrsets.recursiveUpdate.

Practical use cases for adding values conditionally

plymouth is an application that allows you to display a custom splash screen when you boot a Linux machine. To make plymouth useful and avoid disrupting the splash screen with logs, we have to set quiet and splash at boot.kernelParams.

Instead of setting it directly at boot.kernelParams, and comment it out when we disable plymouth, we can use the aforementioned technique, and add those parameters to boot.kernelParams when config.boot.plymouth.enable is true.

configuration.nix
{ config, pkgs, lib, inputs, ... }:

{
  boot.plymouth.enable = true;
  boot.kernelParams = []
    ++ (lib.lists.optionals config.boot.plymouth.enable [ "quiet" "splash" ]);
}

Hugo Sum

A Hongkonger living in the UK. The only thing I know is there is so much I don't know.

Enjoy reading my blog?

Subscribe to a monthly newsletter and join my adventure on software development.

© 2025 Hugo Sum. All Rights Reserved.