Why does the ? operator need the ${...} syntax

When querying if the attribute of an attrset exists, it is not possible to use a variable for the second argument, as illustrated by this example:

nix-repl> s = { a = 1; "b.c" = 2; }
nix-repl> s.a
nix-repl> s."b.c"
nix-repl> p = "b.c"
nix-repl> s ? p
nix-repl> s ? ${p}

Does ${p} as anything to do with interpolation? Why is it necessary and why can’t the ? operator just evalute its second argument?

Because the second operand is an attrPath. So s ? p is querying whether s contains an attribute p. I guess this is done for ergonomic reasons, otherwise every attribute path would require quotes, such as s."a" as opposed to s.a .

I don’t know the answer to the first question. ${p} is an antiquotation, but I am not sure why s ? ${p} is valid syntax (I would expect s ? "${p}"). Maybe the second operand is forced to be a string and then the antiquotation is evaluated?

Edit: a quick grep reveals 36 instances of ? ${ and 17 instances of ? "${ in nixpkgs.

1 Like

s ? ${p} works for the same reason s.${p} works, which is to say, convenience. s.${p} is documented in the manual, and both . and ? are documented as taking an attrpath so it’s only natural that ? takes the same antiquotation that . does.