OFFSET偏移
← 文章目录OFFSET / FIELD NOTESNO. 022

Nix 函数与作用域

辨认 let、inherit、with 和函数参数中每个变量的来源。

所在专题Nix 语言与构建模型 ↗
约 3 分钟阅读开始阅读

"看懂 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);
}

通过 ++ 运算符可以合并两个列表。#

参考与延伸

  1. NixOS 手册 ↗
  2. Nix 语言手册 ↗

根据技术笔记重新整理,示例使用通用名称。

沿专题继续阅读

Nix 语言与构建模型

  1. 01Nix 与 NixOS:存储、回滚和声明式思维
  2. 02Nix 语法:属性集、列表与内置函数
  3. 03Nix 函数与作用域
  4. 04Nix 属性集:递归与合并
  5. 05Derivation:从表达式到构建产物
CONTINUE READING / 下一篇Nix 属性集:递归与合并

区分语言层浅合并和 NixOS 模块选项的合并规则。