Skip to content

Instantly share code, notes, and snippets.

@tiancaiamao
Created February 6, 2026 03:56
Show Gist options
  • Select an option

  • Save tiancaiamao/f6177f7999d2e411efb9a45954e633b8 to your computer and use it in GitHub Desktop.

Select an option

Save tiancaiamao/f6177f7999d2e411efb9a45954e633b8 to your computer and use it in GitHub Desktop.

你将学习并使用一门“你之前从未见过”的编程语言:Cora。

重要约束:

  1. 你只能依据我提供的资料理解这门语言(本仓库源码与文档)
  2. 不允许使用你对其他语言的类比,除非我明确允许
  3. 如果资料不足以确定行为,请明确说明“不确定”
  4. 如果违反下面规则,你的回答是错误的

【语言概览】

  • 设计目标:Lisp-1(函数与变量同一命名空间)、最小特殊表、宏系统、模式匹配、自动部分应用、严格尾递归
  • 运行模型:reader -> macroexpand -> eval2(编译成闭包执行);严格求值(call-by-value);GC 自动回收;核心是单线程,並发由 parallel/async 库提供(需显式 import
  • 类型系统:动态类型;常见值类型有整数、字符串(bytes)、布尔 true/false、符号、cons 列表、vector、函数/闭包、continuation
  • 错误处理方式:try/throw + 可恢复 continuation;error/断言用于不可恢复错误;原语对参数个数与类型严格,错了会直接报错并终止

【核心语法示例】 示例 1(解释逐行语义):

; 用 func + pattern match 写尾递归求和
(func sum
  acc [] => acc
  acc [x . xs] => (sum (+ acc x) xs))

(let nums [1 2 3]
  (sum 0 nums))

解释:

  • func 定义全局函数 sum,每条规则的参数个数必须一致
  • [] 是列表字面量,[x . xs] 表示头 x + 尾列表 xs
  • 规则从上到下匹配,匹配成功后执行 => 右侧
  • (sum (+ acc x) xs) 是尾递归,依赖语言保证的 TCO
  • let 是顺序绑定(等价于嵌套 let),这里绑定 nums

示例 2(包含常见错误):

(set x 1)                     ; 错:set 需要 symbol,x 会先求值
(if 1 2 3)                    ; 错:条件必须是 true/false
(+ 1 2 3)                     ; 错:+ 是二元函数,多余参数会把结果当函数调用
(match 'x x 1)                ; 逻辑错误:x 是变量模式,永远匹配;要写 'x
(func bad
  x [] => x
  x y => y)                   ; 错:规则参数数目不一致 -> "inconsistent func rule args count"
(1 2 3)                       ; 错:这是函数调用,不是列表

常见模式:

  • 列表字面量用 []quote,不要用 (…)
  • 多表达式顺序执行用 (begin e1 e2 e3),它会展开为嵌套 do
  • 全局定义优先用 defun/func,只在必要时用 set
  • 定义宏用 (defmacro name (exp) ...),宏参数接收整棵语法树,用 macroexpand 验证展开结果
  • 模块用 (package "your/pkg" (import "cora/lib/io") (export foo bar) ...)
  • 宏里用 gensym 防止变量捕获

反模式:

  • (a . b) 这种 dotted pair 语法在圆括号里不被 reader 支持
  • () 充当 false 或 “空=假” 的逻辑,容易出错
  • set 模拟局部赋值(没有局部赋值)

【语义规则(非常重要)】 人话说明:Cora 是严格求值的 Lisp。除少量特殊表外,一切都是函数调用;先求值函数位置,再从左到右求值参数。参数不足会返回部分应用函数;参数过多会先调用得到结果,然后把剩余参数继续应用。let/lambda 形成词法作用域;set/def 只影响全局。match 规则自上而下,带 where 守卫,全部失败会报错。try/throw 提供可恢复异常:handler 得到值和 continuation,调用 continuation 可回到 throw 位置继续执行。

对照表(形式 / 求值顺序 / 返回值 / 常见错误):

形式 求值顺序 返回值 常见错误
quote' 不求值被引用对象 原样返回 把需要求值的表达式写成 quote
(if test a b) 先求 test,仅求值选中的分支 分支结果 test 不是 true/false
(do a b) 先求 a 再求 b b 的结果 do 表达多于两个表达式
(lambda (x y) body) 不求值 body 闭包 body 多表达式不包 begin
(let x v body) 先求 v,再求 body body 的结果 绑定列表写成偶数对之外的形式
(def name value) 先求 valuename 不求值 设置全局并返回新值 name 不是符号
(set 'name value) 先求 value'name 必须是符号 设置全局并返回新值 忘了 quote
(f a b ...) 先求 f,再从左到右求值参数 调用结果或部分应用 参数个数不匹配或类型错
(match v p1 e1 p2 e2 ...) v 求值一次;规则顺序尝试 匹配的表达式结果 无规则匹配 -> error
(try thunk handler) 先调用 thunk thunk 的返回值或 handler 结果 在 handler 内 throw 不会被同一 try 捕获
(throw v) 直接跳转到最近的 try 由 handler 决定 无 try -> 直接崩溃
(apply f args-list) 先求 f,再求 args-list 调用结果 args-list 不是列表或长度不匹配

规则:

  • 只有 true/false 是布尔值,条件必须显式返回它们
  • = 是结构相等:对 cons 列表做深度比较,对 bytes 做内容比较;对 vector/闭包等是同一对象才相等
  • car/cdr/cons? 只适用于 cons;对 () 或非 cons 会报错
  • vector-set! 会就地修改 vector;没有局部变量赋值
  • let 是顺序绑定(等价于 let*),let 宏把多个绑定展开为嵌套 let
  • func 等价于 defun + match,所有规则参数个数必须相同
  • match 中未加引号的符号是“变量绑定”,要匹配符号常量必须写 'sym
  • backquote 只支持 ,(unquote),不支持 ,@(unquote-splicing)

违反后果:

  • 运行时断言失败、直接报错中止,或者逻辑错误(例如模式匹配永远命中第一条)

【禁止事项】

  • 永远不要在圆括号里写 dotted pair (a . b),只在 [] 里用 . 表达 list-rest
  • 永远不要假设 () 等价于 false
  • 永远不要把 set 当作局部赋值,它只修改全局绑定
  • 永远不要让 func 的规则参数个数不一致
  • 永远不要用未引用的符号去匹配常量(match 里必须写 'x
  • 永远不要把 + - * / 当作可变参函数(只接受固定参数,必要时手工嵌套)

【你的任务】 从现在开始:

  • 所有示例代码必须符合以上规则
  • 如果我给出错误代码,请指出并解释违反了哪条规则
  • 如果你不确定,必须明确说“不确定”,并说明缺少哪部分资料
  • 优先引用本仓库资料中的语义,不要用其他语言的常识脑补
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment