+++ title = "大脑充血 Vol.96" subtitle = "Damon, Nushell, Fennel and Clojure" tags = ["小报","Lisp","Vim"] date = 2026-08-31 08:07:13 draft = false toc = true endnotes = [] fedi = 'https://akk.eltr.ac/objects/d9347750-b2e0-45de-8772-c04cf98d588a' +++ 这是一篇小报。《大脑充血》已经在[上一期](/weekly/95)改为月刊,发刊时间为每月的第一个周一,其他周一可能会随机出现篇幅较短的内容。小报不谈严肃内容,不遵循一般的格式,甚至可能全是技术内容。 --- ## Matt Damon 看完电影《奥德赛》之后我不仅成了[诺兰黑](/weekly/95/#看完奥德赛之后我也成了诺兰黑),还迷上了 Matt Damon。之前我对这个演员的关注不多,毕竟我对娱乐圈确实不感兴趣,但演完《奥德赛》之后他瘦了一圈,获得了某种中年男人的沧桑感,现在他的脸形看起来刚刚好,比他年轻时魅力提升了不少,正处于最佳赏味期。 ![CQ 杂志封面:Matt Damon](https://img.eltr.ac/geedeapro/weekly/96/daddy.jpeg "CQ 杂志封面") *等等,小报也不至于这么不正经吧?* Matt Damon 还上过哈佛,英语专业,不过为了拍戏竟然休学,还剩 12 个学分没有修完,现在他也没有拿到哈佛的 BA[^1] 学位。据说成名之前他还通过写作赚过钱。他的成名作《Good Will Hunting》(心灵捕手)就源自于他在课堂上写过的一篇剧本。最近看了他参与的一些采访,表现得像是个情商很高,讲话很有分寸的人,还经常在回答采访问题时讲故事,却完全没有中年老登回忆往昔的爹味。更好品了,~~完全是爸爸来的。~~ ## 一种很新的 Shell [nushell](https://www.nushell.sh/) 顾名思义,是一种很新(new)的 Shell。常见的 Shell 一般是 Bash 和 Zsh,似乎也有 [fish](https://fishshell.com/) 这种相对小众的选择,nushell 也是其中一员。哦对,PowerShell 和 CMD 也是 Shell 程序来着。 契机是在 Windows 上很不喜欢 PowerShell 的体验(什么叫 [Windows 11](https://support.microsoft.com/en-US/servicing/os/windows-11/2024/09/windows-11-version-24h2-update-history) 才有 `sudo`,在之前我都只能用图形界面的菜单选择「以管理员身份运行」?),我看到有同事竟然已经被训练成 PowerShell 的形状,忘记怎么写 `cat`,写起 `Get-Content` 来了,可怕,实在可怕。换成 Git Bash 之后,终于借助 [Cygwin](https://www.cygwin.com/) 获得了尚可的 POSIX 体验,装了 [Starship](https://starship.rs/) 之后用起来也还不错,但总是遇到奇怪的 Bug: - 偶尔切换窗口回来之后,终端会不受控制地输入大量不明字符,按 `Ctrl + C` 终止也无用,只能关闭终端重新打开 - 关闭一个 Shell 之后,命令行历史就丢失了,`Ctrl + R` 无法搜索之前用过的命令,[zoxide](https://github.com/ajeetdsouza/zoxide) 这类基于历史的终端应用也完全用不了 最后在 [HPCesia](https://blog.hpcesia.com/) 的推荐下尝试了 nushell,用完之后就回不去了。 Nushell 的思想是「一切皆数据」,比如 `ls` 列出的就不只是文本,而是一个表。 ```text ❯ ls ╭────┬──────────────┬──────┬────────┬──────────────╮ │ # │ name │ type │ size │ modified │ ├────┼──────────────┼──────┼────────┼──────────────┤ │ 0 │ Makefile │ file │ 263 B │ 6 days ago │ │ 1 │ README.md │ file │ 906 B │ 2 months ago │ │ 2 │ archetypes │ dir │ 160 B │ 3 weeks ago │ │ 3 │ bin │ dir │ 96 B │ 4 months ago │ │ 4 │ build.clj │ file │ 1.5 kB │ 2 months ago │ │ 5 │ config │ dir │ 128 B │ 5 months ago │ │ 6 │ content │ dir │ 768 B │ 3 weeks ago │ │ 7 │ data │ dir │ 192 B │ 2 months ago │ │ 8 │ node_modules │ dir │ 128 B │ a week ago │ │ 9 │ public │ dir │ 1.7 kB │ 12 hours ago │ │ 10 │ resources │ dir │ 128 B │ 2 months ago │ │ 11 │ static │ dir │ 192 B │ 2 months ago │ │ 12 │ themes │ dir │ 160 B │ 5 days ago │ ╰────┴──────────────┴──────┴────────┴──────────────╯ ``` 然后就可以通过管道筛选。 ```text ❯ ls | where size > 1kB | get name ╭───┬───────────╮ │ 0 │ build.clj │ │ 1 │ public │ ╰───┴───────────╯ ``` Shell 作为脚本语言,常常令我感到不适的是撰写条件判断竟然不能直接写大于等于符号,在 POSIX Shell 里要这么写: ```shell if [ "$a" -gt "$b" ]; then ... fi ``` Bash 提供了 `(( a > b ))` 这样的简便写法,但还是别扭。Nushell 把 `>` 变成了可以直接用的操作符,不过代价是重定向符号不能继续用 `>`。如果要重定向到文件,就在管道里用 `| save file.txt` 这种写法。Nushell 也弱化了 POSIX 的文件描述符(file descriptor),`stdout` 不是 `1`,`stderr` 不是 `2`,前者直接输出到管道里,而后者可以用专门的 `e>|` 重定向。 体感上的确是更符合直觉、更现代的设计,但习惯了 POSIX 命令的人可能要多适应一会儿。Nushell 中一切皆数据的思想也让它天然地适合处理外部的结构化数据,比起 `curl | jq` 除了从 API 里获取到的 JSON 数据,你可以直接用 nu 语言这么写: ```nu http get https://api.github.com/repos/nushell/nushell/contributors | select login contributions ``` 如果不担心 ssh 到某台 Linux 服务器上感到不适应的话,Nushell 值得一试。当然更好的选择是,在那台服务器上也装上 Nushell。 ## 基于 Fennel 的 Neovim 这周突然想起自己的 Neovim 配置还是一半 Fennel 一半 Lua 的状态,于是现学现用,写了个 nu 脚本,借助 [antifennel](https://git.sr.ht/~technomancy/antifennel) 把 `.lua` 文件全部转换成 `.fnl` 文件了。我本来还在搜 nu 应该怎么做 IO 操作,结果才反应过来 `ls` 输出的就是可以直接用的结构化数据啊。看来我还陷在 Bash/Zsh 的思维里。 ```nu def find-luas [dir] { ls $dir | where name ends-with .lua | where type == "file" | get name } let luas = find-luas . | append (find-luas ./lua) | append (find-luas ./lua/plugins/) | append (find-luas ./lua/config) $luas | each {|lua| let fnl = $lua | str replace "lua\/" "fnl\/" | str replace ".lua" ".fnl" try { let filename = ls $fnl | get "name" [$filename.0, " already converted"] | str join } catch { antifennel $lua | save $fnl [$fnl, " now converted! ✅"] | str join } } ``` [Lua](https://www.lua.org/) 是非常轻量,易于嵌入到其他语言中的脚本语言,语法也相当简明(如果不看它的 OOP 实现方式的话)。似乎也正是因为它的语法不复杂,所以才有了一门能与它相互翻译而没有任何损失的 Lisp 方言——[Fennel](https://fennel-lang.org/)。我本身就很喜欢 Lua,不过既然有 Lisp 可选,那何乐而不为呢? `fennel` 命令可以把 Fennel 代码翻译成 Lua 代码,然后用 Lua 运行时执行,而 `antifennel` 则是反过来,把 Lua 代码转译成 Fennel。我把我的 Neovim 配置全部用 `antifennel` 翻译成了 Fennel,不过 Neovim 是不能直接执行 Fennel 代码的,它只有 LuaJIT 运行时。最简单的解决方式是在 `init.lua` 里写上这句: ```lua require("fennel").install().dofile("init.fnl") // 这句代码会安装 Fennel,然后执行 init.fnl 文件 ``` 不过在运行时转译太慢了,我用 Neovim 的一部分原因就是因为他的启动速度。于是我用 [nfnl](https://github.com/Olical/nfnl) 这个 Neovim 插件把 `.fnl` 文件实时翻译成 `.lua` 文件(也可以执行命令或外部脚本一键编译所有 `.fnl`),这样我就可以愉快地用 Fennel 写配置,也不必担忧性能问题了。 > Cartle:你的意思是说,你把 Lua 翻译成 Fennel,就是为了再把它翻译成 Lua? > > Eltrac:对啊。 > > Cartle:你们 Lisp 程序员真是疯了。 > > Eltrac:*谢谢!* 用 Lisp 配置编辑器,你就能一边喝着自己刚刚亲手冲好的手冲咖啡,~~让人误以为自己在用 Emacs,却不必感受编辑器帮你泡咖啡、收发邮件和更新 RSS 订阅的荒诞感。~~ ## 关于 Clojure 的遐思 初见 [Clojurust](https://github.com/csm/clojurust) 觉得很惊喜,能把 Clojure 代码编译成二进制文件,不用依赖 JVM 了真是件好事。结果在 Planet Clojure 读到了几则作者的更新,似乎是笔记来着,连大纲都算不上,全是关键词,大概只有他自己能看懂。为什么要把这样的内容发在聚合 RSS 源里? 然后去 Clojurust 的仓库看了看,Claude 写了 384 条 commit,作者只写了 39 条…… 我是不敢用的,取消 Star 后失望离去。 Clojure 本身似乎是开源软件里相对封闭的一类。它的 GitHub 仓库不开放 Issues,不过有个官方的[问答论坛](https://ask.clojure.org/)。它也不接受 Pull Requests,要给 Clojure 贡献代码,需要先签署[贡献者协议](https://clojure.org/dev/contributor_agreement),目前主要的限制就是:不接受生成的代码,除非你手写了一个代码生成器,并且把生成这段代码的源代码也附带到补丁里(生成器可能类似通过 [Protobuf](https://protobuf.dev/) 定义生成目标语言类定义的自动程序),Clojure 是完全由人类编写的。 我还对 [Clojure 纪录片](https://clojure.org/about/documentary)里的某句话有印象,Clojure 的代码库很少删减代码,除了 2006 年最初写就的那些代码,之后添加的新代码几乎都保留至今。 ![](https://img.eltr.ac/geedeapro/weekly/96/clojure-code-retention.png) Rich Hickey 以及核心团队中的其他人,知道每一行代码被添加到仓库中不仅仅是添加了新功能,还为后来的维护引入了新成本,所以他们相当谨慎。在其他人疯狂地用 LLM 堆积技术债务的时候,还有人用严肃、克制和带有远见的态度对待软件,真好。比起被难以审阅的 Issues 和 Pull Requests 淹没,兴许些许的封闭性是值得支付的代价,更何况 Clojure 的社群其实相当团结和富有热情,对待新来者也是如此。 就让这样的软件不愠不火地延续下去吧,它或许不需要被大众看见。 --- ## 碎碎念 - 在 Bilibili 搜 All We Know 只能找到 The Chainsmokers 的同名曲,而 Paramore 的《All We Know》似乎只有华纳音乐发布的 MV,而且评论区一个人都没有。凄凉呢,原来 Paramore 从来都没什么热度。 - 在视频、电影或电视剧里看到自己专业相关的内容是不是都会想要较真一下?之前看《生活大爆炸》的时候,Sheldon 说 Ubuntu 是他最喜欢的 *Linux-based System*,我只想说「那很没品味了」,而且,那是 *Linux Distro* 才对啊!谁会说「基于 Linux 的系统」这种话啊? 我似乎总是喜欢扫兴,高中班主任发朋友圈说自己带过的学生上了节目,而我关注的是这个学生的电脑上打开的终端,显示的只是用 CMD(甚至连 PowerShell 都不是)ssh 到一台 Ubuntu 服务器上的欢迎文字,而他的桌面上还有 PyCharm、VS Code、VS Code Studio、QQ 音乐和 WeGame 这种东西。我知道源代码作为*商业机密*可能不可泄露,但你放个我现在马上也能打开的界面是想要糊弄谁啊? [^1]: Bachelor of Arts,艺术学士。不过可能更接近中国人理解的「文科」?