I’m trying to nest two let…in expressions in a script.nix configuration file which adds scripts and .desktop applications, but I have troubles with the syntax.
The idea was to abstract bash script parts to have a tidier script.nix file. I’ll give a useless basic example, keeping my basic structure:
Thanks @jonringer – I thought we had to use rec for this, but reading back the documentation, rec is advised when let expression would create too much clutter, and let can indeed reference to self. Thanks for your help.
the rec you’re thinking of is within an attr set (think dictionary). It allows you to refer to other attrs present in the attr set, the most common example being the old name convention:
stdenv.mkDerivation rec {
name = "hello-{version}";
version = "1.1.0";
still used commonly in today in most sources, but usually in pull sources:
Thanks again @jonringer for your help – I’m still new at NixOS and I’m working at a high level for the moment, even if I sometime have to meddle with some (not so) lower nix level. But that’s fun, and all your inputs are helping me narrowing down my research!
That case was pretty trivial, but what about a more complicated case?
let
pkgs = nixpkgsFor.${system};
in {
default = "something something";
let name = "myname-1"; in {
${name} = pkgs.mkShell {
name = ${name};
#...other stuff...
};
};
let name = "myname-2"; in {
${name} = pkgs.mkShell {
name = ${name};
#...other stuff...
};
};
};
This produces an error from the first nested let expression even if it’s not the first statement in the in body.
I need more than one line within the outer let statement, but I have two other nested let statements that can’t encompass the whole outer let. While it’s technically possible to combine them by giving the name in each of the nested let statements a unique name instead, it kind of defeats the purpose of what I was trying to do.
EDIT: stripped out some specifics from the example that were accidentally left in after copy-paste
For the attribute names you had to use quotes, and for the name = ${name} part you also either had to use quotes ("${name}") or no antiquotation (name).
About “resolving” the lets though, that pretty much defeats the purpose of let. Your answer is basically “don’t do that”, ignoring the very reason let exists in the first place.
Is it simply not possible to ever nest a let inside another let under any condition? That seems very unlikely since nix is supposed to be a functional language and therefore everything must be able to be nested within everything else (“cons” can’t be constructed otherwise).
You can use a let everywhere where an expression is allowed. Though where you used your 2 “inner” lets, no expression was allowed, but attribute names only. That was what I wanted to show you with “resolving” the lets.
So the let is an attribute set generator in this case, so it will return an attribute set that has to go somewhere. The inner lets aren’t being assigned anywhere so there’s nothing to trigger their (potentially lazy) evaluation. It’s not an issue with them being nested.
Clearly I’ve had too many years of C macro programming for my own good.