
作者: 一了1liao3funlang.org日期:2026-09-24 一句话总结: 给 Fun 补上读的一端line/char/all.input()三种模式由接收者字符串选择ok出参区分空行与 EOFLinux 逐字节读 fd0、原始模式读单键Windows 只按行读。附一个「一亿美金级」中文问答 demo。为了那一亿美金的 AI 项目标题不是说笑demo 的开头就写着「一亿美金级 AI 代码请勿轻易扩散偷偷享用」。只是这一亿美金买到的东西是一个 63 行的正则脚本加上解释器里刚补上的一个读标准输入的小内建。Fun 一直有一个短到有点可爱的输出运算符?.把表达式写出一行。读的一端一直是空的 —— 解释器能在自己的语法里打印却读不了一次标准输入。上游b64721c在libase.pas里补上了input内建a3e3917又把 Windows 一侧收干净。这一篇讲这个内建的设计和为它写的那个「AI」demo。一、三种读法由接收者字符串选input注册在CLbase上同一个内建由接收者字符串决定行为exp.asStr就是那个接收者linecharall各自进一个分支。var lineline.input();# 读一行行尾去掉var keychar.input();# 读一个按键终端上为原始模式var restall.input();# 读到输入结束可选参数是提示串位置传参或命名prompt:都行它经env.echo写出因此和?.一样服从运行器的日志GUI 设置var qline.input(Q: );二、和 nil 相等所以要有 ok 出参line与char在输入结束时返回nilall只是把剩下的都给你没有则。麻烦在于Fun 把和 nil 判为相等一个空行和一次 EOF从返回值上看不出区别。只靠返回值读循环没法知道自己该不该停。于是内建留了第二个出参传一个变量位置第二或命名ok:它收到「本次是否真读到东西」。demo 里的循环正是这么写的var ok;var q;loop qline.input(Q: , ok: ok);exitwhen not ok or q;# 空行 / Ctrl-D 都会结束?.A: reply(q);end loop;读放在循环顶部既不需要循环前预读一行末尾也不用再补一次。三、为什么绕开 RTL 的文本设备最省事的实现是让 RTL 的ReadLn去读。它没有这么做原因在平台差异Linux直接从 fd 0 逐字节读三种模式都成立UTF-8 终端原样透传。char靠termios把终端切进原始模式关掉ICANON、ECHO设VMIN1、VTIME0读到一个字节后立刻tcsetattr恢复line保持规范模式回显与行编辑仍交给终端。Windows保持简单只走 RTL 的ReadLn文本按本构建的字符串编码返回ANSIDelphi 2009 为 Unicode一个多字节字符不会被拆成半个。char与all在那边等同line。四、demo一亿美金的 AIfun/demo/input.fun就是那个「一亿美金的 AI」63 行读中文问题用几条正则重写后回答。规则只有三条其中动词重叠是按结构匹配、不靠词表fun reply(q)resultq.replace(/(.{1,3})(不|没)\1/g,$1);# A不A / A没A - Aresultresult.replace(/你|我|您/g, m -m.value()我and你or我);resultresult.replace(/(吗|吧|呢)?(\?|)/g,!);# 疑问句尾 - !end fun;于是你会聊天吗?→我会聊天!你有没有钱?→我有钱!称呼也跟着翻。两个实现细节值得记一下内置的 PCRE 没编 UTF-8 支持模式是在字节上跑的.{1,3}对 ASCII1 字节、GBK2 字节、UTF-8 汉字3 字节都恰好匹配一个字符。但多字节字面量必须用交替不能塞进[...]字符类 —— 字符类会把它们的字节拆开、错位。单行替换的回调是箭头 lambda你我您的互换用了cond and a or b这个 if-else 惯用法条件真则取前者否则取后者。脚本开头还有一段免责声明中英各一份# 一亿美金级 AI 代码,请勿轻易扩散,偷偷享用;# 倘若有人问起,就说你只是随手敲了两行正则。五、跑法与验证交互式跑fun/funcmd fun/demo/input.fun也可以当过滤器用管道进去就行printf你会聊天吗?\n|fun/funcmd fun/demo/input.fun验证Linux x86_64 上三种模式都跑通 —— 管道逐行喂问题得到预期回答char一次一个按键换行也算一个all取走余下整个流空行或 Ctrl-D 结束会话作者提交说明里另记了真实终端pseudo-terminal上的原始单键检查。完整回归run-linux-regression.sh87/88唯一未过的是input-console.sh的本地快照它在之后几次 demo 文案改动提示语、空行处理后没重新生成脚本的实际输出是对的。一个 Windows 上的坑写在 demo 注释里GBK 控制台交回来的是 GBK 字节脚本里没有可移植的切换办法试过defaultCodePage.set(65001)对这次读取没有影响。要么把文件存成 ANSI/GBK 再跑要么用funu.exe。Linux 控制台本来就是 UTF-8不用操心。结语读进一行是脚本语言第一次真正碰到终端的地方难的不是那个while而是语言自己的不变量Fun 里 nil于是「空行」和「没有」在返回值上塌成了一件事。解法不是把这两个值分开那是动语言根基而是给读循环一个显式的出参 (ok)让它能确认到底读到了没有。写终端交互的人迟早都会撞上这堵墙早点用一个变量把它标清楚比事后猜 EOF 便宜得多。至于那「一亿美金」—— 它当然只值两行正则。但一个能读终端的解释器确实让这份脚本从「只会打印」变成了「能对话」这个关子卖得不算亏。