大脑充血 Vol.96

这是一篇小报。《大脑充血》已经在 上一期 改为月刊,发刊时间为每月的第一个周一,其他周一可能会随机出现篇幅较短的内容。小报不谈严肃内容,不遵循一般的格式,甚至可能全是技术内容。

Matt Damon

看完电影《奥德赛》之后我不仅成了 诺兰黑 ,还迷上了 Matt Damon。之前我对这个演员的关注不多,毕竟我对娱乐圈确实不感兴趣,但演完《奥德赛》之后他瘦了一圈,获得了某种中年男人的沧桑感,现在他的脸形看起来刚刚好,比他年轻时魅力提升了不少,正处于最佳赏味期。

等等,小报也不至于这么不正经吧?

Matt Damon 还上过哈佛,英语专业,不过为了拍戏竟然休学,还剩 12 个学分没有修完,现在他也没有拿到哈佛的 BA 学位。据说成名之前他还通过写作赚过钱。他的成名作《Good Will Hunting》(心灵捕手)就源自于他在课堂上写过的一篇剧本。最近看了他参与的一些采访,表现得像是个情商很高,讲话很有分寸的人,还经常在回答采访问题时讲故事,却完全没有中年老登回忆往昔的爹味。更好品了,完全是爸爸来的。

一种很新的 Shell

nushell 顾名思义,是一种很新(new)的 Shell。常见的 Shell 一般是 Bash 和 Zsh,似乎也有 fish 这种相对小众的选择,nushell 也是其中一员。哦对,PowerShell 和 CMD 也是 Shell 程序来着。

契机是在 Windows 上很不喜欢 PowerShell 的体验(什么叫 Windows 11 才有 sudo,在之前我都只能用图形界面的菜单选择「以管理员身份运行」?),我看到有同事竟然已经被训练成 PowerShell 的形状,忘记怎么写 cat,写起 Get-Content 来了,可怕,实在可怕。换成 Git Bash 之后,终于借助 Cygwin 获得了尚可的 POSIX 体验,装了 Starship 之后用起来也还不错,但总是遇到奇怪的 Bug:

  • 偶尔切换窗口回来之后,终端会不受控制地输入大量不明字符,按 Ctrl + C 终止也无用,只能关闭终端重新打开
  • 关闭一个 Shell 之后,命令行历史就丢失了,Ctrl + R 无法搜索之前用过的命令, zoxide 这类基于历史的终端应用也完全用不了

最后在 HPCesia 的推荐下尝试了 nushell,用完之后就回不去了。

Nushell 的思想是「一切皆数据」,比如 ls 列出的就不只是文本,而是一个表。

❯ 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 │
╰────┴──────────────┴──────┴────────┴──────────────╯

然后就可以通过管道筛选。

❯ ls | where size > 1kB | get name
╭───┬───────────╮
│ 0 │ build.clj │
│ 1 │ public │
╰───┴───────────╯

Shell 作为脚本语言,常常令我感到不适的是撰写条件判断竟然不能直接写大于等于符号,在 POSIX Shell 里要这么写:

if [ "$a" -gt "$b" ]; then
 ...
fi

Bash 提供了 (( a > b )) 这样的简便写法,但还是别扭。Nushell 把 > 变成了可以直接用的操作符,不过代价是重定向符号不能继续用 >。如果要重定向到文件,就在管道里用 | save file.txt 这种写法。Nushell 也弱化了 POSIX 的文件描述符(file descriptor),stdout 不是 1stderr 不是 2,前者直接输出到管道里,而后者可以用专门的 e>| 重定向。

体感上的确是更符合直觉、更现代的设计,但习惯了 POSIX 命令的人可能要多适应一会儿。Nushell 中一切皆数据的思想也让它天然地适合处理外部的结构化数据,比起 curl | jq 除了从 API 里获取到的 JSON 数据,你可以直接用 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.lua 文件全部转换成 .fnl 文件了。我本来还在搜 nu 应该怎么做 IO 操作,结果才反应过来 ls 输出的就是可以直接用的结构化数据啊。看来我还陷在 Bash/Zsh 的思维里。

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 是非常轻量,易于嵌入到其他语言中的脚本语言,语法也相当简明(如果不看它的 OOP 实现方式的话)。似乎也正是因为它的语法不复杂,所以才有了一门能与它相互翻译而没有任何损失的 Lisp 方言—— Fennel 。我本身就很喜欢 Lua,不过既然有 Lisp 可选,那何乐而不为呢?

fennel 命令可以把 Fennel 代码翻译成 Lua 代码,然后用 Lua 运行时执行,而 antifennel 则是反过来,把 Lua 代码转译成 Fennel。我把我的 Neovim 配置全部用 antifennel 翻译成了 Fennel,不过 Neovim 是不能直接执行 Fennel 代码的,它只有 LuaJIT 运行时。最简单的解决方式是在 init.lua 里写上这句:

require("fennel").install().dofile("init.fnl")
// 这句代码会安装 Fennel,然后执行 init.fnl 文件

不过在运行时转译太慢了,我用 Neovim 的一部分原因就是因为他的启动速度。于是我用 nfnl 这个 Neovim 插件把 .fnl 文件实时翻译成 .lua 文件(也可以执行命令或外部脚本一键编译所有 .fnl),这样我就可以愉快地用 Fennel 写配置,也不必担忧性能问题了。

Cartle:你的意思是说,你把 Lua 翻译成 Fennel,就是为了再把它翻译成 Lua? Eltrac:对啊。 Cartle:你们 Lisp 程序员真是疯了。 Eltrac:谢谢!

用 Lisp 配置编辑器,你就能一边喝着自己刚刚亲手冲好的手冲咖啡,让人误以为自己在用 Emacs,却不必感受编辑器帮你泡咖啡、收发邮件和更新 RSS 订阅的荒诞感。

关于 Clojure 的遐思

初见 Clojurust 觉得很惊喜,能把 Clojure 代码编译成二进制文件,不用依赖 JVM 了真是件好事。结果在 Planet Clojure 读到了几则作者的更新,似乎是笔记来着,连大纲都算不上,全是关键词,大概只有他自己能看懂。为什么要把这样的内容发在聚合 RSS 源里?

然后去 Clojurust 的仓库看了看,Claude 写了 384 条 commit,作者只写了 39 条…… 我是不敢用的,取消 Star 后失望离去。

Clojure 本身似乎是开源软件里相对封闭的一类。它的 GitHub 仓库不开放 Issues,不过有个官方的 问答论坛 。它也不接受 Pull Requests,要给 Clojure 贡献代码,需要先签署 贡献者协议 ,目前主要的限制就是:不接受生成的代码,除非你手写了一个代码生成器,并且把生成这段代码的源代码也附带到补丁里(生成器可能类似通过 Protobuf 定义生成目标语言类定义的自动程序),Clojure 是完全由人类编写的。

我还对 Clojure 纪录片 里的某句话有印象,Clojure 的代码库很少删减代码,除了 2006 年最初写就的那些代码,之后添加的新代码几乎都保留至今。

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,艺术学士。不过可能更接近中国人理解的「文科」?
添加评论
点赞收藏
点踩分享查看原文
评论
?
参与讨论