Skip to content

《爻象设计宣言》锐评

版本:v2.0.0(毕竟”正式发布”的草稿也是发布)
状态:颅内高潮
作者:晨煦 + 尚未聚集的”社区”
日期:2026-05-31(来自未来,但编译器还在昨天)


「道生一,一生二,二生三,三生万物。」
—— 《道德经》

类型如道,万物皆由此生。
(程序员如蝼蚁,皆由此卷。)


一、为什么创造 YaoXiang?—— 因为世界显然缺第514种语言

1.1 填补的语言空白

在编程语言的历史长河中,我们见证了无数语言诞生、流行、然后被扔进历史的垃圾桶。但我们不一样——我们敏锐地发现了一个惊天空白:竟然没有一门语言能同时让 Rust 爱好者觉得太简单、让 Python 用户觉得太复杂、并且让 AI 模型在生成代码时感到“舒适”

需求现有解决方案的问题我们的解决方案(预计)
类型安全Rust 太严苛,TypeScript 太松我们将创造一种既严苛又松散的量子叠加态类型系统
自然语法别人家的语法都不自然我们的语法将自然到让你忘记自己在编程(也可能是因为看不懂)
AI 友好AI 生成代码常出错我们将为 AI 设计语法,人类可以顺便用用

1.2 解决的实际问题

问题一:类型系统的碎片化
我们提出「一切皆类型」,这解决了“有些东西不是类型”这个令人困扰的哲学问题。现在连你的代码缩进都可以是一个类型(IndentationLevel<4>)。

问题二:内存安全与性能的二选一
我们最初采用 Rust 的所有权模型,但发现"借用检查器"太难实现。于是灵机一动——把 &T&mut T 从"引用"重命名为"令牌",宣布它们是"零大小的编译期权限证明"。现在不需要借用检查器了,只需要"流敏感活性分析"——听起来完全不一样,对吧?如果程序有数据竞争,那一定是令牌的品牌机制出了问题。

问题三:异步编程的认知负担
我们重新发明了轮子,并给它起名叫“并作模型”。只需一个 spawn,编译器就会自动处理所有异步细节——如果处理不了,那是你代码写得不“并作”。

问题四:AI 辅助编程的瓶颈
我们贴心地为 AI 设计了严格缩进和明确边界,确保 GPT-7 在生成代码时不会精神分裂。至于人类程序员能不能看懂……那是次要的。

1.3 语言的哲学根基

YaoXiang 的名字源于《易经》,这确保了它在技术讨论中自带神秘学 buff。当代码无法编译时,你可以说:“这是阴阳未调,待我起一卦看看。”


二、核心哲学与原则 —— 不容置疑的圣训

2.1 原则一:一切皆类型

不可妥协的理由:这样我们可以用类型论解释一切,包括为什么项目进度总是延迟。

2.2 原则二:严格结构化

不可妥协的理由:4空格缩进是宇宙真理。用 Tab 的人应该被流放到火星。

2.3 原则三:零成本抽象

不可妥协的理由:虽然我们的抽象层有 7 层,但因为是“零成本”的,所以性能应该和手写汇编差不多……理论上。

2.4 原则四:默认不可变

不可妥协的理由:可变性是万恶之源。如果你需要修改变量,那说明你设计错了。

2.5 原则五:类型即数据

不可妥协的理由:这样我们可以在运行时检查类型,然后发现……编译时已经检查过了。


三、关键创新与特性 —— 重新发明已经发明过的东西

3.1 创新一:统一类型语法

我们废除了 enumstructuniontraitimpl 这些令人困惑的概念,然后又废除了 type 关键字本身。现在一切都用 name: Type = value。记住,Type 不是关键字——它是保留字,不要问区别在哪。

3.2 创新二:构造器即类型

消除了”类型”与”值”的鸿沟,创造了新的鸿沟:”这到底是个类型构造器还是个值构造器?哦等等,它们现在用同样的语法了,更分不清了。”

3.3 创新三:柯里化方法绑定

我们通过柯里化实现了方法调用。现在你可以用 Type.method = function[0] 代替 self 参数。显然更直观。[0] 表示"把第 0 个参数当作 self",如果忘了写 [0],编译器会告诉你"这不是方法,这是普通函数"。简单!

3.4 创新四:所有权模型(RFC-009 v9)

五个概念,一个梯度:&T&mut T、Move、refclone()unsafe。等等那是六个。没关系——&T&mut T 是"令牌",不是"引用"。区别?引用是 C++ 的概念,令牌是编译期零大小的类型级权限证明。当你的代码无法编译时,你可以说"类型属性 Dup/Linear 推导失败",没人敢反驳你。

令牌系统还附带这些高级功能:

  • freeze:把 &mut T "冻结"成 &T。就像把生鲜放进冰箱——解冻之前不能烹饪。编译器用"流敏感活性分析"追踪冻结状态,听起来像 ICU 监护仪。
  • 品牌机制:每个令牌在编译期被分配唯一整数(品牌 #N),用于防伪造。"对不起先生,您的 &Point 令牌品牌 #42 与所有者胶囊中的品牌 #43 不匹配。"
  • 不能跨任务:令牌是"编译期权限证明",不能穿线程。如果需要跨任务共享,请用 ref。为什么?因为编译器说不行。实际上是因为令牌在编译后就消失了——零大小类型,零运行时开销,也零跨任务能力。

总结:Rust 用 200 页 The Book 解释借用检查器。YaoXiang 用"&T 可复制,&mut T 不可复制"两句话解释一切。简单就是美。

3.5 创新五:并作模型——整个语言最烂的部分

「万物并作,吾以观复。」——《易·复卦》

并作模型的核心卖点:同步语法,异步本质。翻译成人话:你的代码看起来是顺序执行的,但运行时会自动并行。什么时候并行?怎么并行?编译器说了算。这不是并发模型,这是一场信任游戏。

来看看为了实现这个魔法,我们往语言里塞了什么:

spawn 关键字:标记一个函数是异步的。注意——不是 async,是 spawn。因为 async 太主流了。但 spawn 在 Rust 里是"启动一个任务"的意思。没关系,我们重新定义它。

@block 注解:标记一个 spawn 函数应该"同步执行"。等等——如果 spawn 是异步,@block 让它同步,那为什么不直接不写 spawn?"因为有时候你需要一个 spaw 函数在某些上下文中同步运行。"所以一个标注了 spawn 的函数可能异步也可能同步,取决于调用方的心情。这不是类型系统,这是人格分裂。

@eager 注解:标记需要"急切求值"的表达式。因为并作模型默认惰性求值——虽然惰性求值还没实现。所以目前 @eager 的实际作用是什么?它是一张欠条:"将来有一天,当惰性求值实现时,这个注解会让表达式不被惰性求值。"

总结并发模型的三个注解

spawn  = 这个函数会异步(除非被 @block 了)
@block = 这个 spawn 函数这会是同步的(覆盖 spawn)
@eager = 这个表达式将来不会被惰性求值(你先别管将来)

如果你觉得这很混乱,恭喜你——你理解了。当你的代码并行崩溃时,你可以引用《易经》,显得很有深度。

3.6 创新六:值依赖类型(RFC-011)

现在你可以在编译期证明你的数组长度是质数,矩阵维度必须匹配,factorial(5) 的结果可以用在类型签名里。虽然这跟写业务逻辑没什么关系,但"类型即命题,程序即证明"——你说酷不酷?

别忘了decreases 规约:所有编译期求值的递归函数必须证明自己会终止。不然你的类型检查器会陷入无限循环,然后你的 IDE 会变成一个空间加热器。"对不起,你的 factorial 函数缺少 decreases 规约。编译器不知道它会不会在 n=-1 时递归到宇宙热寂。"

3.7 创新七:极简关键字设计

只有 17 个关键字!比 Go 少 8 个!虽然每个关键字的含义是 Go 关键字的 3 倍复杂,但数量上我们赢了。注意:type 不是关键字——它在 RFC-010 中被移除了。现在你用 name: Type = value,其中 Type 是保留字。关键字和保留字的区别?不要问,问就是编译器内部宇宙层级 Type0/Type1/Type2 的问题。

3.8 创新八:Curry-Howard 同构——万能解释法

每当有人质疑设计决策,标准回答是:"这遵循 Curry-Howard 同构。"不懂?没关系,社区里没人真懂。大意是"类型即命题,程序即证明",所以你的代码不仅是程序——它是一篇数学论文。编译错误就是反证法。

这一哲学的最高成就是 RFC-010 的彩蛋:Type: Type = Type。尝试编译这行代码,编译器不会崩溃——它会输出一段禅意消息,大意是"道可道非常道,类型可类型非常类型"。这是 YaoXiang 对 Girard 悖论的致敬,也是唯一一个编译器故意不实现的功能。我们称之为"语言边界"——当你触达它时,编译器在此沉默,哲学在此驻足。


四、初步语法预览 —— “看起来能工作”的代码示例

yaoxiang
# === Hello World(可以在脑中运行) ===
main: () -> Void = {
    print("Hello, 未来的贡献者!")
}

# === 所有权模型:五个概念(其实是六个) ===
Point: Type = { x: Float, y: Float }

p1 = Point(1.0, 2.0)
p2 = p1              # Move。p1 安息吧。
p2.print()           # 编译器创建 &Point 令牌。令牌品牌 #4201,请查收。
p2.shift(1.0, 1.0)  # 编译器创建 &mut Point 令牌。独占!其他令牌退避!
shared = ref p2      # ref = 共享。编译器自动选 Rc。或者 Arc。你不需要知道。
backup = p2.clone()  # 深拷贝。为什么不用 ref?因为 ref 不是拷贝,是共享。懂?

# === 统一语法:name: type = value ===
# 你能看出下面哪个是类型,哪个是函数,哪个是变量吗?
# 答案:看不出来。这就是"统一"的美。
identity: (T: Type) -> ((x: T) -> T) = x
List: (T: Type) -> Type = { data: Array(T), length: Int }

# === 值依赖类型:把阶乘写在类型签名里 ===
factorial: (n: Int) -> Int = {
    # decreases: n  ← 不写这个编译器会恐慌
    if n <= 1 { return 1 }
    return n * factorial(n - 1)
}
vec: Vec(factorial(5)) = Vec(120)()  # Vec(120) 类型,编译期计算

# === 并作模型:spawn + @block + @eager = 三位一体的混乱 ===
fetch_data: (url: String) -> JSON spawn = {
    return HTTP.get(url).json()
}

@block  # 这一行让上面的 spawn 函数在这调用时变成同步的
main: () -> Void = {
    data = fetch_data("https://api.example.com")  # 同步?异步?看心情。
}

# @eager:标记"将来惰性求值实现后不要惰性求值这里"
result: Int eager = heavy_computation()  # 目前跟没写一样

# 总结:
# spawn = 异步(除非 @block)
# @block = 把 spawn 变同步
# @eager = 将来不做某事(现在什么都没发生)
# 三个概念加起来 = if else

以上代码在文档中运行良好。实际编译结果可能有所不同。不,是一定不同。


五、路线图与待定项 —— 梦想清单

5.0 RFC 依赖三角

在了解路线图之前,先来欣赏 YaoXiang 最精妙的架构设计——RFC 三角恋:

RFC-009 (所有权)  →  依赖 RFC-010 (统一语法)  →  依赖 RFC-011 (泛型)
    ↑                                                         │
    └──────────────────── 依赖 ────────────────────────────────┘

009 需要 010 的语法,010 需要 011 的泛型,011 需要 009 的类型系统。三个 RFC 互为前提。先实现哪个?"建议同步实现。"——RFC-010 第 141 行。

这就是 Curry-Howard 同构在实际工程中的体现:每个 RFC 都是一个命题,它们的依赖关系构成一个逻辑循环。打破这个循环需要引入一个外部公理——也就是"我们先把类型检查器写死,以后再说"。

5.1 已决定的设计决策

不再接受更改,除非我们改了主意。

5.2 待讨论的设计议题

包括“字面量语法”、“泛型推导”、“模式匹配”等琐碎细节。核心哲学已经完美,这些小事可以慢慢来。

5.3 实现路线图

v0.1: Rust 解释器 ✅
v0.5: 字节码编译器 🔄 (进行中,已经进行了18个月)
v1.0: 生产就绪   ⏳ (等我们找到第10个贡献者)
v2.0: 自举       ⏳ (当我们在 v1.0 中解决了时间旅行问题后)

5.4 当前实现状态

  • 词法分析器:✅ 100%(可以识别 spawn 这个词)
  • 语法分析器:✅ 100%(可以解析 spawn 后面应该有点什么)
  • 类型检查器:✅ 95%(可以判断 42Int 类型,但 Type 的宇宙层级还在争论中)
  • 所有权令牌系统:✅ 100%(设计文档完成。实现?那是下一步的事。)
  • RFC 文档:✅ 14篇已接受(平均每篇 800 行。代码?什么代码?)
  • 实际能运行的代码:🔴 0%

六、如何参与贡献 —— 请带上你的时间、热情和降低的期望值

Cargo.toml 中记载的 authors:["YaoXiang Team", "ChenXu2333"]。Team 与 ChenXu2333 并列。经考证,Team 当前规模为 1 人。但"Team"这个复数形式给人以无限遐想空间。

6.1 设计讨论

适合人群:喜欢在理论上辩论“单子是不是自函子范畴上的幺半群”的人。

6.2 编译器实现

适合人群:有闲置的脑细胞,且不介意它们被用来实现第 7 种内存管理模型。

当前最需要的贡献:

  • 令牌冲突检测:实现"流敏感活性分析"。别担心,名字虽然长,但原理很简单——就是追踪每个令牌在函数体内的状态:活跃、冻结、已移动。就像追踪三个小孩在游乐场的位置。只不过小孩可能会无限递归。
  • 跨任务环检测 lint:检测 ref 的跨任务循环引用。默认 warn,可配 deny。我们需要有人决定:warn 的措辞应该多严厉?"Warning: cross-task cycle detected" 还是 "Warning: 你的代码形成了跨任务环,虽然不会泄漏但你应该感到羞耻"?

6.3 工具链开发

需要开发的工具:LSP 服务器、调试器、格式化工具、包管理器……一切。特别是 LSP——当用户在 Type: Type = Type 上悬停时,应该弹出"不可名状之物"的 tooltip。

6.4 标准库建设

std.iostd.gui,应有尽有。目前有的:std.placeholder。下一步计划:std.placeholder_v2

6.5 文档翻译

我们需要把 14 篇 RFC 翻译成英文。每篇平均 800 行。总共约 11200 行。考虑到 RFC 中充满了"并作""爻象""万物并作吾以观复"等概念,这大约等价于翻译半部《道德经》。报名从速。

6.7 贡献指南

提交信息格式:必须是诗。十四行诗优先。Haiku 也可接受:

所有权令牌
编译之后消失不见
零成本抽象

附录C:常见问题

Q: YaoXiang 与 Rust 相比有什么优势?
A: 更少的语法糖!更少的关键字!更少的实用功能!但更多的哲学深度。另外我们有一个”借用令牌系统”——听起来比”借用检查器”高级,对吧?

Q: YaoXiang 适合做什么类型的开发?
A: 适合开发 YaoXiang 编译器。以及写设计宣言和 RFC。其他用途待研究。

Q: 为什么选择 4 空格缩进?
A: 2空格太密,8空格太疏,4空格恰如中庸之道,符合《易经》精神。

Q: Type 是关键字吗?
A: 不是。它是”保留字”。关键字和保留字的区别在于:关键字会出现在语言规范的关键字列表中,保留字则出现在”注意:以下不是关键字”的列表中。简单明了。

Q: 为什么有 14 篇已接受的 RFC 但版本号还是 0.7.0?
A: 因为我们在下一盘大棋。设计先行,实现随后。非常随后的那种随后。

Q: ref 到底是 Rc 还是 Arc?
A: 编译器自动选择。不需要你操心。实际上,这是编译器唯一比用户更懂的时候,所以我们充分放权。

Q: “并作模型”什么时候能真正工作?
A: 当你看到这行字的时候,答案仍然是”设计阶段,未实现”。但 spawn 关键字已经可以正确解析了,这难道不令人振奋吗?

Q: 什么时候会发布 1.0 版本?
A: 当”社区”从 1 人扩展到 2 人时。

Q: 如何联系核心团队?
A: 在 GitHub Discussions 留言。回复时间:1-3 个业务月。


七、更多的谎言

"多语言支持"docs/src/{en,ja,ru,zh} 四语齐全。编译器 v0.7.0,实际能跑的代码行数大约等于零,但日本和俄罗斯的开发者已经可以用母语阅读"并作模型"和"值依赖类型"了。这是经典的"文档驱动开发"——先让全世界读懂你的设计,再假装有人需要它。等编译器能跑 Hello World 的时候,文档已经翻译成克林贡语了。

工具链套娃:Python 的 pre-commit 检查 Rust 的代码风格(cargo fmt + clippy),Rust 编译器编译 YaoXiang 源码。三层语言叠在一起,每一层都依赖下一层。等到 YaoXiang 自举,这个套娃会变成:Python 检查 Rust,Rust 编译 YaoXiang,YaoXiang 编译 YaoXiang。到那时,一个 upstream 依赖挂了,整个工具链就变成行为艺术。但这没关系——"自举"这个词本身就值两篇 RFC。

YaoXiang-book.md:一本系统讲述 YaoXiang 语言的书。写一本书来描述一个还没实现的编程语言,相当于为一个不存在的城市出版旅游指南。"第三章:泛型系统——本章代码均无法编译,但语法是正确的。请想象运行结果。"整本书最诚实的一句话是第一页的"项目状态:实验验证阶段"。

"无 GC":官方口径:"YaoXiang 无 GC。"严格来说,没有 tracing GC。但 ref 在运行时是引用计数(Rc/Arc)。引用计数算不算 GC?"不算。GC 是 garbage collection,引用计数是 automatic reference counting。你看,缩写都不一样。一个是 GC,一个是 ARC。完全不同。"这种文字游戏的意义在于:当有人说"你们这不就是引用计数 GC 吗",你可以义正词严地说"不,我们没有 GC,只有编译器自动管理的引用计数"。区别在哪里?在 PPT 上。

最后更新:2026-05-31(可能是最后一次更新,但你永远不知道)

文档版本:v2.0.0(我们版本号跳得很快,这样显得进度快)

许可证:MIT(反正现在只有 MIT 文件)


「爻象变化,万物生焉。类型演化,程序成焉。」

愿 YaoXiang 的设计之旅,能成为您茶余饭后 津津乐道的谈资
(毕竟现阶段,它主要是个谈资。)