nixnixos

Why do Nix lambdas and the ? operator interact like so?


While trying out nix & nix repl:

Welcome to Nix version 2.3.6. Type :? for help.

nix-repl> pkgs = import <nixpkgs> {}

nix-repl> builtins.typeOf pkgs
"set"

nix-repl> pkgs ? "firefox"
true

nix-repl> func = (n: pkgs ? "firefox")

nix-repl> func null
true

nix-repl> func = (n: pkgs ? n)

nix-repl> func "firefox"
false

I assumed that func "firefox" would return true.

What Nix paradigms or concepts explain why func "firefox" returns false in this example?


Solution

  • The thing you write after ? is not an expression: it is an attribute path. This allows you to do powerful things like pkgs ? hello.src which probes to see whether pkgs has an attribute named hello which has an attribute named src.

    When Nix evaluates a ? b, Nix just looks at the name "b", it does not consider whether "b" is a variable in the local context. So pkgs ? n is true if an only if pkgs is a set with a member that literally is named "n".

    Here is an example repl session that explores the issue. The last line shows a possible solution for what I think you are trying to do.

    nix-repl> pkgs = import <nixpkgs> {}
    nix-repl> pkgs ? "firefox"
    true
    nix-repl> pkgs ? "name"
    false
    nix-repl> name = "firefox"
    nix-repl> pkgs ? name
    false
    nix-repl> firefox = "name"
    nix-repl> pkgs ? firefox
    true
    nix-repl> pkgs ? "${name}"
    true
    nix-repl> builtins.hasAttr name pkgs  
    true