Jacquard 完全指南:面向 AI 生成代码的编程语言——让语言本身回答”它能碰什么,我们有多确定”
概述
当 AI 编码工具能在几秒内生成整段函数时,代码审查的瓶颈从”写不出来”变成了”看不完”。一段代码能访问文件系统吗?会发起网络请求吗?如果 API 挂掉了会怎样?这些问题的答案通常藏在数千行代码的角落,需要逐行阅读才能确认。
Jacquard 是一个 FriendMachine 研究项目开发的编程语言,专为”AI 编写、人类审核”的场景设计。它不是又一款 AI 编码助手,而是一套让代码的意图在语言层面就可见可查的编程范式。在 Jacquard 中,函数的签名不仅告诉你返回什么类型,还告诉你它可能执行哪些外部效应——是否访问网络、读写文件、或者执行动态代码。这些信息是语言规范的一部分,不是注释,不是文档,不是”记得在 PR 里写清楚”。
核心设计思想:当代码由机器编写时,语言本身必须承担更多责任
Jacquard 的核心理念可以浓缩为一句话:当大多数代码由机器编写时,审核的人类需要语言本身来回答”它能碰什么,我们有多确定”,而不是逐行阅读每一行代码。
这体现在三个层面:
- 效应可见:每个函数的签名明确声明它可能执行的外部效应(网络、文件系统、控制台等)。未声明的效应会被运行时拒绝,除非显式授权。
- 世界可换:同一份代码可以在真实网络、录制的流量回放、或概率模拟中运行——无需修改代码本身。
- 身份稳定:代码的身份基于语义结构而非源文本的哈希。重命名变量、调整格式、添加注释——这些操作不会改变代码的规范身份。
架构揭秘:27 个内核形式与代数效应
Jacquard 的语言内核极其精简——只有 27 种形式。所有语法结构(.jac 表面语法)都是这 27 种形式的投影表示。语言统一使用 (head, meta, args) 三元组作为数据表示,引用的代码就是普通的数据。
架构的核心是代数效应处理器:
- 深层的、多重恢复的处理器:一个处理器可以将计算恢复零次、一次或多次。这意味着穷举搜索和精确概率推理可以写成普通的库代码——不需要专门的测试框架或建模语言。
- 显式能力授权:运行时只为你在
--allow中指定的效应安装处理器。没有环境权限。想访问网络?必须显式声明:--allow net。 - 类型-效应行列:每个箭头类型都携带该函数可能执行的效应集合——程序的推断类型就是它的权限清单。
安装与快速上手
Jacquard 的安装出奇地简单——不需要 OCaml 编译器(除非你想从源码开发):
curl -fsSL https://raw.githubusercontent.com/jbwinters/jacquard-lang/jacquard-core-0.1-rc3/scripts/install.sh | sh
安装脚本会自动检测你的操作系统和 CPU,下载匹配的压缩包和 SHA-256 校验和,检验通过后安装到 ~/.local/。
确保 ~/.local/bin 在 PATH 中:
jacquard --version jac --version
jac 是 jacquard 的短别名。来跑第一个 Jacquard 程序——计算 5 的阶乘:
jac run ~/.local/share/jacquard/demos/basics/m1-fact.jac
预期输出是 120。
CLI 命令完全参考
Jacquard CLI 包含 8 个核心子命令:
| 命令 | 功能 |
|---|---|
jac run FILE.jac | 运行程序,可选 --allow fs/--allow net 授权 |
jac check FILE.jac | 类型检查,输出签名和效应清单 |
jac hash FILE.jac | 计算代码的规范身份哈希 |
jac fmt FILE.jac | 自动格式化代码 |
jac diff A B | 规范结构差异比较(支持文件和存储) |
jac infer | 概率推理(enumerate 穷举 / lw 似然加权) |
jac test TESTS.jac | 运行 Warp 测试,支持穷举模式和缓存 |
jac build FILE.jqd -o PROG | 原生编译为独立可执行文件 |
深入三个核心特性
1. 效应追踪:一眼看出函数能做什么
在 Jacquard 中,函数签名不仅包含返回类型,还包含它可能执行的效应。一个签名如 (text) ->{net} text 表明该函数可能执行 net(网络)效应:
fetch_url : (url) ->{net} String
如果一段 AI 生成的代码尝试访问网络但未声明 net 效应,运行时会在执行前拒绝——不是运行时错误,而是语言级的安全保障。
2. 多世界测试:同一代码,无数环境
这是 Jacquard 最强大的能力之一:相同的代码可以在不同的”世界”中运行,无需任何修改:
jac run my-agent.jac --allow net jac replay trace.jqd my-agent.jqd jac infer enumerate MODEL.jac
这种能力使得全面的错误处理测试变得简单——不是 mock,不是桩代码,而是同一个程序在真正不同的世界处理器中运行。
3. 规范身份:重命名不改变代码身份
Jacquard 对代码的身份是基于规范语义结构哈希的,而非源字节。这意味着:
- 重命名局部变量 → 身份不变
- 调整格式化 → 身份不变
- 添加注释 → 身份不变
- 修改逻辑 → 身份改变
这个特性对 AI 生成代码的审核流程特别有价值:如果一段 AI 生成的代码经过人工审核后确认正确,其规范哈希可以被”锁定”。后续任何实质变更都会产生不同的哈希,触发重新审核。
Demo 示例:程序修复作为贝叶斯推理
Jacquard 最令人印象深刻的 demo 展示了编程语言设计如何将程序修复变成贝叶斯推理问题:
sh ~/.local/share/jacquard/demos/tooling/repair.sh
流程是这样的:
- 一个包含 bug 的程序被编译为带引号的 AST
- 系统对每个可能的单点编辑生成候补补丁——8 个候选
- 将失败的测试视为观察证据,计算每个补丁的后验概率
- 一个修复测试后,正确补丁的概率升至 0.75,一个”作弊”补丁占 0.25
- 添加一个回归测试后,作弊补丁概率归零
这个流程不需要专门的测试框架——它就是语言本身的能力。代数效应引擎让”生成候补 → 执行 → 观察 → 更新概率”成为一个普通的库调用。
原生编译
Jacquard 支持将程序编译为独立可执行文件(C 后端):
export JACQUARD_PRELUDE=$PWD/prelude export JACQUARD_RUNTIME=$PWD/runtime jac build demos/tooling/word-count.jqd -o word-count echo "hello world" | ./word-count --allow console
编译后的可执行文件输出与解释器字节一致——标准输出、标准错误和退出码都被差异测试验证过。支持的效应包括 console、clock、fs、dist 和 infer。
当前限制
Jacquard core 0.1 是一个研究原型,不是生产平台:
- 没有 JIT 编译器或虚拟机
- 没有并发支持
- 没有连续概率分布
- 没有包管理系统
- 效应授权仍然比较粗粒度
详细限制清单见 docs/release/0.1/LIMITS.md。项目以令人耳目一新的诚实态度记录了每一项已知局限——这是 AI 工具生态中不多见的透明度。
总结
Jacquard 代表的不是”又一个 AI 工具”,而是一种对 AI 生成代码时代编程语言应该承担什么责任的重新思考。当 Claude Code 和 Codex 能在几秒内生成整段业务逻辑时,传统的”我逐行审查每一行代码”模式已经不可持续。Jacquard 用语言本身解决了”这代码能干什么”的问题——不需要离线审查、不需要安全检查表、不需要在 PR 评论里来回确认。
对于那些在 AI 编码工具日益普及的团队中负责代码质量和安全的人来说,Jacquard 值得持续关注——它展示了编程语言设计的未来方向。
- GitHub: https://github.com/jbwinters/jacquard-lang
- 研究介绍: https://research.friendmachine.co/jacquard/
- 许可证: Apache-2.0