"看懂 Nix 代码的关键在于:知道这个变量是从哪来的。"
变量定义:let ... in#
这是最常用的局部变量定义方式。
let
myUser = "alice";
myShell = pkgs.zsh;
in {
users.users.${myUser} = {
shell = myShell;
};
}- 规则:
let绑定在各绑定值及in后表达式中可见,因此绑定可相互引用;不会泄露到表达式外。
简写魔法:inherit#
当你想把一个同名变量赋值给一个属性时,可以使用 inherit。
常规写法:
{
git = pkgs.git;
vim = pkgs.vim;
}使用 inherit 简写:
{
inherit (pkgs) git vim;
}这在 flake.nix 和模块配置中极其常见。
危险警告:with pkgs;#
with set; body 给 body 增加属性查找范围;已有词法绑定优先,不会把属性变成普通 let 绑定。
with pkgs; [ git vim htop ]- 风险:容易造成变量名冲突,且难以调试(不知道某个变量到底是来自
pkgs还是全局作用域)。 - 建议:在列表
[ ... ]里使用没问题,但在大的配置块里尽量少用。
函数与参数解析#
Nix 文件的顶层通常是一个匿名函数:
{ config, pkgs, lib, ... }: {
# 配置内容
}...(Ellipsis):表示该函数接受更多参数,但我现在不需要它们(防止参数不匹配导致的报错)。- 解构赋值:你可以直接在花括号里指定你需要的参数名。
实战技巧:嵌套作用域#
let
commonPkgs = with pkgs; [ git vim ];
in {
environment.systemPackages = commonPkgs ++ (let extra = [ pkgs.htop ]; in extra);
}通过 ++ 运算符可以合并两个列表。#
参考与延伸
根据技术笔记重新整理,示例使用通用名称。