记号作用域 = 小理论(导入闭包),而非整个 vault
这个 vault 远比一篇 LaTeX 论文庞大,所以用单一的扁平前导(preamble)/注册表是错的(会撞名、无法维护)。作用域问题的答案是 sTeX 的小理论(little theories)。
规则
- 每个笔记 = 一个小理论;一个符号宏在其所属笔记(home note)中声明(
\Variety声明于 ashby)。 - 一个笔记可以使用某个符号,当且仅当该符号的所属笔记落在这个笔记的传递导入闭包内(沿着
> Prereq:/[[…]]遍历——即"树桩"搜索)。 - 作用域 = 导入闭包,而非整个 vault。
为什么庞大的 vault 不是问题
小理论之所以能撑住规模,正是因为你从不需要同时持有所有符号——只需要一个笔记的导入闭包(几十个,而不是成千上万个)。Lean mathlib / sTeX 档案库(两者都极其庞大)正是这样运作的:V 在不同的闭包里代表不同的东西,这是设计使然。vault 的大小与作用域的大小是正交的——vault 再大,也不会进入符号消解(resolution)的计算。
冲突只发生在同一闭包内
V@ashby(多样性 variety)与 V@adaptive-commitment-value(期权价值)是不同的理论 → 永不冲突——除非某个笔记同时导入了两者,那时才需要取别名/消歧(这种情况很少见)。所以作用域化消解了"全局混淆"这个担忧:不用维护一份全局注册表,只需维护逐笔记的闭包。
Obsidian 的桥接(唯一的一点小麻烦)
Obsidian 的 MathJax 没有逐笔记导入的编译器(sTeX 有)——只有全局前导或逐笔记的 \newcommand。所以:
- 在所属笔记中声明;
- 渲染:生成一份全局前导,使用全局唯一的宏名(例如
\ashbyV);渲染器忽略作用域; - 作用域由 lint 强制执行:一个笔记只能使用那些所属笔记落在自身导入闭包内的宏;一个名字若在闭包内产生歧义 → 要求"消歧"。渲染是全局的,使用由 lint 逐笔记限定作用域。
命名旋钮
- 方案 A:全局长名
\ashbyV——零歧义,不需要编译器,但写在公式里很啰嗦; - 方案 B:逐笔记的短别名——每个笔记开头写
$\newcommand\V{\ashbyV}$,正文用\V;简短,作用域在别名那一行就写明了,lint 检查该别名指向的目标是否在闭包内。选方案 B。
一句话总结
作用域 = 每个笔记的 prerequisite/link 传递闭包(一个小理论),而不是整个 vault;不管 vault 有多大,符号消解永远只针对一个闭包——这正是 Lean mathlib 能撑住规模的原因。Obsidian 从一份全局唯一命名的前导渲染;lint 强制执行真正的逐笔记作用域。参见 notation-checking-prior-art。