奇语是什么,为什么用中文关键字
奇语(Qi)是一门编译型语言:源码经词法分析、LALRPOP 生成的语法分析、AST、再到 LLVM IR,最终用 clang 链接成原生可执行文件。它没有解释器,跑起来就是机器码。
它最显眼的特点是全中文关键字:函数、变量、如果、否则、当、对于、返回。这不是噱头——对中文母语者,把控制流读成自然语言能显著降低初学者的认知负担,也让代码审查时「意图」一目了然。标点上中英文都接受:()【】;, 和 (){};, 等价。
本文所有代码都来自仓库里的一个示例文件,并用 qi 编译器真实跑过;文中的终端输出是真实输出,不是手写的。
结果、类型、选项、通道、数组、任务、返回、等待 等。中文母语者很自然会写 变量 结果 = ... 或 变量 任务 = ...——这些会触发解析错误。改个名即可,比如 结果值、翻倍任务、数列。安装与第一个程序
每个奇语程序都需要一个包声明和一个名为 入口 的函数(等价于其他语言的 main)。注释用 //,和 C/Rust 一样。
包 主程序;
函数 入口() {
打印行("你好,Qi!");
}
用 qi run 一步编译并运行:
$ qi run 你好世界.qi
你好,Qi!打印行 输出后换行;打印 则不换行。要只做语法检查不生成可执行文件,用 qi check 文件.qi。
变量与基本类型
用 变量 声明可变变量,常量 声明不可变常量。类型可以省略让编译器推断,也可以用 名字: 类型 显式标注。
变量 名字 = "奇语"; // 类型推断:字符串
变量 年龄: 整数 = 1; // 整数(底层 i64)
变量 圆周率: 浮点数 = 3.14159; // 浮点数(f64)
变量 启用: 布尔 = 真; // 布尔:真 / 假
打印行("语言: ", 名字, " 年龄: ", 年龄);
常用基本类型:整数(默认 64 位)、浮点数(64 位)、字符串(UTF-8)、布尔(真/假)。需要更窄的整数可用 短整数、字节。打印行 可以接收多个参数,会依次拼接输出。
整数 映射的是 64 位的 i64,不是 32 位。浮点数打印会按 C 的 %f 风格输出(例如 3.14159 会显示成 3.141588 这样的近似),需要精确格式时自己控制位数。函数与返回
函数用 函数 声明,参数写 名字: 类型,返回类型写在参数表后的冒号之后,用 返回 返回值。无返回值的函数省略返回类型即可。
函数 加法(甲: 整数, 乙: 整数): 整数 {
返回 甲 + 乙;
}
// 在 入口() 里调用:
打印行("3 + 4 = ", 加法(3, 4));
3 + 4 = 7控制流
三种主力结构:条件分支 如果 / 否则、while 风格的 当、以及遍历数组的 对于 … 在 …。注意条件不需要括号。
// 如果 / 否则
如果 启用 == 真 {
打印行("圆周率约等于 ", 圆周率);
} 否则 {
打印行("未启用");
}
// 对于:遍历数组字面量
对于 i 在 [1, 2, 3] {
打印行("循环第 ", i, " 次");
}
// 当:while 循环
变量 计数 = 0;
当 计数 < 3 {
计数 = 计数 + 1;
}
打印行("计数累加到 ", 计数);
圆周率约等于 3.141588
循环第 1 次
循环第 2 次
循环第 3 次
计数累加到 3对于 遍历的是数组字面量 […],目前不支持 1..4 这样的区间语法。需要无限循环用 循环 { … 跳出; },跳过本次迭代用 继续。自定义类型与方法
用 类型 定义结构体,字段写成「类型在前、字段名在后」并以分号分隔。方法采用 Go 风格:接收者写在函数名前面的括号里,用 自身 访问字段。
类型 矩形 {
浮点数 宽;
浮点数 高;
}
// 方法:接收者写在函数名前的括号里
函数 (自身 矩形) 面积(): 浮点数 {
返回 自身.宽 * 自身.高;
}
// 在 入口() 里:用括号包裹的结构体字面量实例化
变量 矩 = (矩形 { 宽: 3.0, 高: 4.0 });
变量 面: 浮点数 = 矩.面积(); // 先存入有类型的变量再打印
打印行("矩形面积 = ", 面);
矩形面积 = 12.000000浮点数 的变量,再打印。如果直接写 打印行("面积 = ", 矩.面积()),当前编译器会在 IR 生成阶段丢失返回值类型、误用整数格式而报错。把中间结果落到带类型的变量上是稳妥写法。字符串与标准库速览
字符串用 + 拼接。标准库通过 导入 标准库.X 引入,函数用 . 访问(也支持 :: 静态方法形式)。文本处理在 标准库.文本 里(同时也注册为 标准库.字符串)。
导入 标准库.文本;
// 在 入口() 里:
变量 问候 = "你好," + 名字 + "!";
打印行(问候);
打印行("是否包含「奇」: ", 文本.包含(问候, "奇")); // 1 = 是
变量 数列 = [10, 20, 30];
打印行("数组首项 = ", 数列[0]);
你好,奇语!
是否包含「奇」: 1
数组首项 = 10标准库还提供大量模块:标准库.输入输出(文件读写、控制台)、标准库.JSON、标准库.HTTP、标准库.网络(TCP/UDP)、标准库.时间、标准库.加密、标准库.随机、标准库.正则 等。许多 FFI 函数有自己的返回约定(文本函数失败返回空串、布尔型多数 1=成功),用前留意。
异步:未来<T> 与 等待
奇语内置 M:N 协程调度(多个协程跑在少量 OS 线程上,配合工作窃取调度器)。表层 API 很简洁:一个返回 未来<整数> 的函数,返回 的值会被自动包装成 Future;用 等待 取出结果。
// 返回 未来<整数> 的函数,返回值自动包装为 Future
函数 异步翻倍(数值: 整数): 未来<整数> {
返回 数值 * 2;
}
// 在 入口() 里:
变量 翻倍任务: 未来<整数> = 异步翻倍(21);
变量 结果值: 整数 = 等待 翻倍任务; // 等待协程完成并取值
打印行("异步翻倍(21) = ", 结果值);
变量 就绪: 未来<整数> = 未来::就绪(7); // 静态方法构造已就绪的 Future
变量 就绪值: 整数 = 等待 就绪;
打印行("就绪值 = ", 就绪值);
异步翻倍(21) = 42
就绪值 = 7未来、等待、任务 都是保留字。给变量起名要避开它们——上面用了 翻倍任务 而不是 任务,用了 结果值 而不是 结果。未来::就绪(x) 是构造一个立即就绪 Future 的静态方法,适合把已有值塞进异步流程。把它跑起来
上面所有片段都来自同一个示例文件 教程_语言核心.qi。完整文件一条命令即可运行:
$ qi run 教程_语言核心.qi
===== 奇语语言核心 =====
语言: 奇语 年龄: 1
圆周率约等于 3.141588
3 + 4 = 7
循环第 1 次
循环第 2 次
循环第 3 次
计数累加到 3
矩形面积 = 12.000000
你好,奇语!
是否包含「奇」: 1
数组首项 = 10
异步翻倍(21) = 42
就绪值 = 7
===== 全部完成 =====下一步
掌握了语言核心,就可以去用奇语写的三个框架做点真东西:
- qi-web 快速上手 —— Express/Fiber 风格的 HTTP 路由、中间件,热路径有 Rust 加速(约 122k RPS)。
- qi-cli 快速上手 —— Cobra 风格的命令树,子命令、局部/持久标志、别名、执行钩子。
- qi-harness 快速上手 —— 可观测、可重试的 LLM Agent 框架,封装
标准库.大模型,支持流式与工具调用循环。
更系统的语法与标准库参考见文档。动手把本文的示例改一改、跑一跑,是最快的入门方式。