阅读视图

发现新文章,点击刷新页面。

我为什么喜欢音乐剧?

跟一些朋友聊起音乐剧的时候,他们似乎都不太能接受演戏演到一半突然唱起来的举动。不过,音乐剧和迪士尼电影还是有些不同(尽管我也很喜欢迪士尼电影里的歌!)。在音乐剧里,音乐和舞蹈不仅起抒情作用,还是叙事载体,是推动剧情发展的重要一环。

音乐可以用来描绘人物的内心活动,比如《摇滚红与黑》里的《Ding Dong》和《汉密尔顿》里的《Satisfied》;音乐可以展现人物之间的冲突,比如《地狱客栈》里的《Hell’s Greatest Dad》和《魔法坏女巫》里的《What Is This Feeling?》;同一首曲子可以由不同的角色演唱,用相似的旋律展现不同的情感和人物形象,比如《Dear Evan Hansen》里的《Requiem》,甚至相同的旋律在不同的场景响起时,会有不同的效果,这种手法叫作 Reprise。

当然,也少不了一些纯粹的幽默,比如同样是《Dear Evan Hansen》里的《Sincerely Me》,我相当喜欢这首。还有一种歌曲形式叫作 Patter Song ,节奏非常快,歌词的每个音节几乎都是连着的,而且用词通常是押尾韵或者头韵,听感很欢快,不需要什么唱功和技巧。这种歌通常可以快速地推进情节和交代大量信息,很有趣。

音乐里有个概念叫作 motif,通常译作「动机」「乐想」,也音译做「母题」。音乐动机是一段旋律、反复出现的几个突出的音形、一小段音乐片段,可以理解为「用来辨别音乐主题的最小单元」。1在一些音乐剧和歌剧里,人物有各自的动机,出场时场上会响起同一段反复出现的旋律,与人物个性相关。不过,我并不确定这是不是常用于音乐剧的手法,我只知道《地狱客栈》这部音乐剧动漫里使用了这种手法,里面所有的主要人物都有他们出场自带的背景音乐,甚至有代表乐器,比如主角夏莉的乐器是中提琴,她的女友维姬是钟琴。

说了这么多,你可能会以为我是个音乐迷,所以会喜欢音乐剧。我确实偶尔会听点古典乐,但真的很少,我听过的也是那些非常出众,或者非常有个性的,比如贝多芬的第九交响曲(《欢乐颂》就在其中)和巴赫的《咖啡康塔塔》;说实话,我的音乐品味很「流行」,比起古典乐,我更喜欢 Lady Gaga。

我喜欢音乐剧的原因,和音乐本身的关系其实不大。

在这之前要先解释清楚什么是音乐剧。和许多人的第一印象不同,音乐剧并不是什么高雅的艺术形式,实际上相当通俗。人们常常把音乐剧(Musical Theater)和歌剧(Opera)搞混,毕竟,真的有一部名为《歌剧魅影》的音乐剧。对普通人来说,区别实在不明显。

简单来说,歌剧重点在「歌」,而音乐剧重点在「剧」。歌剧的歌唱通常是连续的,不会被情节、对话和动作打断,而音乐剧的歌唱间隙可能会插入对话和其他台词,甚至歌词本身就可能是对话。此外,音乐剧往往会有更多的舞蹈和娱乐性表演,说是歌舞剧可能更准确。由于音乐剧重点在「剧」,所以理解台词以及歌词就很重要,不然会跟不上剧情,然而,聆听外语歌剧是很常见的,就算听不懂词,也能欣赏音乐。

对话穿插在歌唱中,而歌曲本身作为叙事载体推进剧情的例子,可以听这首:

Ready For This music cover

Ready For This

《Hazbin Hotel》

由于音乐剧的表演通常很戏剧化(这个词用在这里貌似很不准确,音乐剧本来就是戏剧),人物的动作很夸张,情感很丰沛,将这种情感与音乐结合在一起就显得格外富有感染力。在我看来,这也是音乐剧可能会被认为不够高雅的另一个原因:情感的表现不够矜持和细腻。无论是快乐、痛苦还是悲伤,都相当夸张。

我能想到的例子是《魔法坏女巫》,这本来是一部小说改编的音乐剧,在最近两年被搬上了电影大荧幕。如果仔细观察 Nessa(也就是主角的妹妹,东方坏女巫)在原版音乐剧和电影版中的表现,就会发现电影版 Nessa 的表现几乎可以说是淡漠,没有音乐剧的那种歇斯底里。由于音乐剧版本的原声带里没有收录《The Wicked Witch of the East》这首歌,所以读者可以参考 这个视频 对比区别。

我向来更喜欢饱满的情感,就像喝咖啡也更喜欢日晒处理的咖啡豆(这类豆子一般风味浓烈,带有更多的水果风味),如果要剖析的话,大概和我童年没有受到太多关爱有关——但说实话,这类话题谈得多了,已经有些庸俗了。

除了情感更饱满,我还更喜欢音乐剧的粉丝群体。说起来,音乐剧是音乐和舞台剧的奇妙组合,这也导致人们对音乐的要求更低,对剧情的要求也更低。这并不是说音乐剧在这两方面都不行,而是说,我很少发现有人对音乐剧的音乐或者剧情做出极端的负面评价。

一方面,不少音乐剧都改编自本身口碑就很好的小说或电影,比如《摇滚红与黑》改编自司汤达的《 红与黑 》,《雨中曲》改编自同名电影。另一方面,当所有人都沐浴在听觉和视觉的双重洗礼下,没有人会把心思放在批评上。回想起来, 去年年底 去剧院看过《雨中曲》之后,我就相信不会有人讨厌音乐剧,也很少会对某个特定的音乐剧做出负面评价。

由于我所在的地方几乎没人看音乐剧,所以当时剧院卖不出去票,但即便人只坐满了不到一半,观众的掌声和喝彩依旧很激烈。音乐剧的舞台是很大的场面,场上能站很多人,在有这么多人的地方还能编排好舞蹈,而舞蹈又能与剧情的场景完美融合在一起,本身就很令人佩服。我印象最深的是开场舞,剧情里应该是电影的拍摄现场,我记得甚至有演员站在剧院后台会用来挂衣服的小推车上跳舞,同时还有另一个人推动着他。

音乐剧的剧情衔接也不需要很巧妙地换场和紧密的逻辑,我还记得《Make ‘Em Laugh》这首歌演唱到一半,演员为了演示「如何让观众大笑」,甚至直接在舞台上表演撞大墙。倘若是其他的叙事媒介,看到有人在毫无预兆的情况从不知道什么地方搬来一块泡沫墙壁,还真的撞破了,真的会觉得有些奇怪,除非是喜剧。

若难以理解,可以想象单独的舞蹈作品,除非编排得很烂,否则很少有人会觉得舞蹈难看,夸张的肢体动作非常吸引注意力。现在,想象这个舞蹈者一边跳舞一边唱歌,歌曲不仅节奏抓耳,歌词也朗朗上口;他的旁边还有很多伴舞,都穿着颜色鲜艳的服装,身体大幅度地摆动着;除了伴舞,可能还有对手,他们唱歌和跳舞都有来有回;而这一切都在发生的同时,故事还在发展,很快就会有冲突、不速之客、意外和转折。

说真的,这样的表演难道不能让你全心全意地投入进去吗?难道不会让你甘愿放下手机,把全部的感官和注意力都献给演员们吗?难道不会让你觉得社交媒体和短视频上碎片化的娱乐信息都食之无味吗?

我每天沉浸在对技术的钻研、对人文社科的探索和无止尽的软件开发以及运维工作当中,尽管富有热情,但总归会感到疲乏。至少我最近明显地感觉到,大量脑力活动过后,我会感到心情低落,这可能是大脑活动消耗了很多糖,血糖快速降低导致的(因为心情低落的同时,我还会感到饿)。

这种情绪波动可能是生理和心理的双重作用,但无论如何,我需要将思绪从西西弗斯的命运中暂时抽离出来,投入一项关注身体感官而非精神和直觉的活动,将我的感官完全交给一支管弦乐队、一群剧场演员和背后的剧作家与作曲家。在那里,我不会看到有人讨论某部剧的续集和后几季如何毁了这部作品,不会看到有人动不动就要给编剧寄刀子,不会有人不合时宜地对情节的合理性发出自以为是的质疑。我会把我的心灵,暂时地,全部献给在我眼前上演的艺术。

如果真的有人不喜欢音乐剧?那就……

The Guy Who Didn't Like Musicals music cover

The Guy Who Didn't Like Musicals

《The Guy Who Didn't Like Musicals》

Should we kill him?
该不该杀了他?

Should we kill him?
该不该杀了他?

Oh, he pines after a cute lil’ barista
噢,他追求那个可爱的小咖啡馆服务生

Isn’t that worth a show-stopping fiesta?
难道不值得一场震惊四座的狂欢?

But for some damn reason, he won’t join our singing seaon
但出于某些原因,他不愿意加入我们的歌唱季

What an ass, what a bitch, what a cock
真是个蠢货,一个婊子,一个傻屌

The guy who didn’t like musicals…
那个不喜欢音乐剧的人……

Webmention 简明指南

Webmention 是一个 W3C 推荐标准, IndieWeb 很喜欢这个标准,甚至制订了名为 Salmention 的拓展,只可惜 Webmention 本身就没什么人用,太小众了,这个拓展标准更是没多少人跟进和实现。对于独立博客来说,这项技术其实相当有用,实现起来也不复杂,但中文博客中支持发送和接收 Webmention 的很少,中文资料也几乎没有。

本文意在解释什么是 Webmention、如何使用它,以及如何让自己的网站支持 Webmention。

什么是 Webmention?

在即时聊天软件和社交媒体中,用户可以使用 @用户名 的格式提及另一个用户,对方会收到通知,知道他被提及了。 这是相当有用的功能,只可惜一般的提及功能是局限于某个平台上的,没办法跨平台通知,比如,如果你使用 Telegram,就没办法提及 QQ 上的用户。Webmention 虽然不是用来解决这个问题的,但它的确提供了一种分布式社交的能力,允许某人在一个网站上提及另一个网站上的内容。

假设 Alice 发布了一篇文章,URL 是 https://alice.blog/interesting-post,而 Bob 读到之后觉得很不错,在自己的网站上写了一篇文章,可能是回应,可能是表达喜爱,也可能只是简单地提及了,Bob 的这篇文章的 URL 是 https://bob.site/cool-stuff

这便是 Webmention 的应用场景。如果 Alice 的网站支持 Webmention,那么 Bob 就可以向 Alice 的网站发送 Webmention,这样 Alice 就知道她写的内容被提及了,她也可以把 Bob 文章的链接展示在网页下,让其他人也知道 Bob 写了一篇回应。

这个过程是如何发生的呢?

Webmention 其实很简单,它只是 HTTP 请求。首先,Bob 要找到 Alice 网站用于接收 Webmention 的端点,向这个地址发送 POST 请求,请求包含两个值,sourcetarget——前者是 Webmention 的源地址,也就是 Bob 的文章,Webmention 是从他的网站发送过来的;后者是目标地址,也就是 Alice 的文章,是 Webmention 要发送到的地方。

如果你不懂什么是 HTTP 请求,可以这样理解:当你在一个博客的评论区填写名字、邮箱地址和评论内容并点击发送按钮之后,你就向这个网站接收评论的端点发送了一条 HTTP 请求,准确来说,是 POST 类型的 HTTP 请求,而 Webmention 也是相同的请求,不过请求发送到的端点不同,请求的内容也不同。

Alice 的服务器通过这个端点接收到了 HTTP 请求之后,就会检查这是不是有效的 Webmention。有效性的要求很低,只要 sourcetarget 都是有效的 URL,source 真的包含了 target 链接(即真的提及了 target),就视作有效,没有其他格式要求。接收到 Webmention 之后要怎么处理,W3C 没有做规范,完全取决于接收端怎么实现。

这里有必要说明一下,Webmention 只是技术标准,而不是具体的软件。就像你可以使用不同的邮件客户端发送电子邮件,发送出去的邮件其他人用不同的客户端也能正常查看,就是因为电子邮件是开放标准,而不是具体的软件。

没什么好讲的了,Webmention 就是这么简单:一个网页提及了另一个网页,这个网站向对方网站发送 POST 请求来通知对方,对方网站接收这个请求。

如何发送 Webmention?

你不需要对自己的网站做任何修改就能够发送 Webmention,因为它只是一个 POST 请求。接收端不会验证请求的来源,仅仅是验证 sourcetarget 两个 URL,所以你可以从任何地方发送请求。

比如,使用 curl

curl \
 -d 'source=https://bob.site/cool-stuff&target=https://alice.blog/interesting-post' \
 https://alice.blog/webmention

注意这里的 https://alice.blog/webmention,这是 Alice 博客的 Webmention 端点,也就是 Webmention 要被发送到的地方。要找到这个端点很简单,只需要检查 Alice 博客的 <head> 标签,找到 rel="webmention"<link> 标签。

<head>
 <link rel="webmention" href="https://alice.blog/webmention">
</head>

这是标准的,声明 Webmention 端点的方式,也是其他人知道 Alice 的网站支持 Webmention 的判断依据。向这个地址发送 POST 请求,Alice 的 Webmention 接收器就会收到请求。

不过,一般没有人会用命令行发送 Webmention,这太不友好了。很多支持 Webmention 的博主会在网站上放一个输入框和一个按钮,表示你可以在这里输入你的文章 URL,然后点击发送,对方就能接收到 Webmention 了。这个表单做起来非常简单,我会在下一节「如何接收 Webmention 讲到」。

只要是能够发送 POST 请求的方式,都能够用来发送 Webmention。一般来说,发送 Webmention 的过程会被自动化,每当有一篇新文章被发现,就检查这篇文章里包含的外部链接,然后逐个请求这些外部链接,检查它们有没有声明 Webmention 端口,如果有,就向这个端口发送 Webmention。

发送 Webmention 的自动化工具

webmention.app 提供了发送 Webmention 的工具,最简单的方式是使用 API。假设你在一篇 URL 为 https://my.site/post-xxx 的文章里包含了一些外链,你想向这些链接发送 Webmention,那么你可以向这个地址发送 POST 请求:

POST https://webmention.app/check/?url=https://my.site/post-xxx

这样就通知了 webmention.app,让它帮你检查你这篇文章里包含了哪些外链、哪些支持 Webmention,然后向有接收端的链接发送 Webmention。你可以在他们的首页最下方的输入框输入你的 URL 并点击「START」,来测试自动发送。

如果要做到全自动,那也很简单。最方便的情况是:你有一个 RSS 订阅源。这样,就可以用 IFTTT 创建一个工作流,在 RSS 更新时通知 webmention.app 检查你的新文章,并帮你发送 Webmention。具体见 这个教程

如果你不想依赖 IFTTT 这样的服务,那就要根据你的网站架构来决定实现方式了。

如果你的网站是动态的,使用 WordPress 或 Typecho 等动态博客软件构建,那么你可以找一找有没有实现了 Webmention 的插件可以使用。我找到了 WordPress 插件 ,其他的软件需要读者自行搜索。

如果你的网站是静态的,使用 Hugo、Astro、Hexo、11ty 等静态网站生成器构建,那么你可以参考 我给 Hugo 添加自动发送 Webmention 能力 的方法。我用到了 @remy/webmention 这个 NPM 包,是命令行工具,在网站构建完成后用这个命令行工具扫描一遍 RSS 源,即可向文中提及的外部链接发送 Webmention。不必担心多次构建会重新发送 Webmention 的问题,接收端要是多次收到了相同的 Webmention,会做查重处理,这是标准里规定了的。

具体怎么在构建完成后自动执行这个命令,要看你使用的静态网站生成器。如果是基于 Node.js 开发的,比如 Hexo,可能会有类似这样的写法:

"scripts": {
 "postbuild": "webmention public/index.xml --limit 1 --send"
},

其他可以参考的链接:

如果觉得太难了,不配置自动发送也可以。手动发送反而更方便把控什么时候发送,什么时候不发送,毕竟有的时候可能不想要打扰别人。

如何接收 Webmention?

显然,你需要一个 Webmention 接收器。如果你的博客是用 WordPress 构建的,前文提到的 插件 已经具备了接收 Webmention 的功能。如果是其他博客软件,可能要考虑使用第三方 Webmention 接收器,或者自己部署接收器了。

使用 webmention.io

最简单也是最常用的第三方 Webmention 接收服务是 webmention.io ,我也在使用。这个服务是免费且开源的,所以还算值得信赖。要使用他们的服务,你首先需要配置 IndieAuth ,也就是表明你是这个网站的主人,怎么做到呢?

在网站的 <head> 添加:

<link rel="me" href="https://github.com/alice">
<link rel="me" href="https://twitter.com/alice">
<link rel="me" href="mailto:alice@mail.com">

alice 改成你自己的用户名。这个标记的意思是,这个网站的主人有 GitHub、Twitter 和电子邮箱账号,用户名或地址如上。接下来,确保你的 Twitter 账号页面或 GitHub 账号资料里有链接到这个网站。这样一来,你就证明了自己拥有这些账号,IndieAuth 也就允许你用这些账号登录。你不必配置全部三个账号,只需要一个有效的登录方式。如果是邮箱的话,IndieAuth 就会给你发送一封电子邮件确认登录。

你还可以把 <link> 写成 <a> 标签,如果网页里已经有这些账号页面的链接了,只需要给 <a> 加上 rel="me" 即可。这种标记方式叫作 microformats,后文还会提到。

配置好 IndieAuth 之后,在 webmention.io 输入域名登录,接下来会进入仪表盘。现在,你需要在 <head> 里面指定 webmention.io 作为接收器,添加这段内容:

<head>
 <link rel=webmention href=https://webmention.io/你的域名/webmention>
</head>

接下来 webmention.io 就能够帮你接收 Webmention 了。这个服务是 Aaron Parecki 提供的,如果你觉得不错,可以去支持他!他还是 IndieWebCamp 的创始人和 OAuth 工作组的编辑者。

好了,现在你能接收 Webmention 了,数据存放在 webmention.io 的服务器里,要怎么查看接收到的 Webmention 呢?有这样几种方式:

  1. 仪表盘 查看最近的 Webmention。
  2. 设置 获取 RSS/Atom 订阅源,使用 RSS 阅读器查看。
  3. 配置 Webhook ,在有新 Webmention 时向指定 URL 发送 HTTP 请求,可以配合 Barkntfy 推送到你的手机上。
  4. 通过 API 获取数据。

如果你想通过 API 把 Webmention 展示在自己的网站上,最简单的方法是使用 webmention.js 。把 JavaScript 文件放在自己的网站上之后,在需要显示 Webmention 的地方添加:

<div id="webmentions"></div>
<script src="/path/to/webmention.min.js" async></script>

具体的使用方式见项目文档。

如果能力允许,可以自己编写渲染逻辑,毕竟 API 已经有了。

自托管 Webmention 接收端

webmention.io 很好用,配合 webmention.js,甚至不需要自己写一行代码,不需要部署任何服务,就能接收并展示 Webmention,这对大部分人来说已经够了。不过,如果你很在乎自己的数据,并希望尽可能少依赖第三方服务,那么你大概要自己部署接收端了。

在可以自己部署的 Webmention 接收端中,使用者比较多的是 Horst Gutmann 维护的 webmentiond ,用 Go 编写,存储基于 SQLite,简单轻量。此外还有用 Rust 编写的 WesleyAC/webmention-receiver 和用 Python 编写的 capjamesg/webmention-receiver

对于重复造轮子这件事,我们国人也不输(奇怪的比较)。 Chlorine 不久前用 Rust 写了一个 Webmention 接收端,名为 CircleAt ,而我也用一门 Lisp 方言开发了 Weepinbell ,最近才发布 v0.1.0 版本。不过我不建议你用 Weepinbell,因为还没有正式投入使用,可能存在一些问题,进入稳定版本之后我会再发一篇文章的。当然,如果你愿意贡献的话,我将感激不尽。

在开始之前,我得警告读者,Webmention 作为一门小众技术标准,使用者很少,自托管接收器的更少,如果遇到问题,可能很难找到解决方案和能够提供帮助的人(虽然我很欢迎有人来问我啦)。如果对自己的技术没什么信心,webmention.io 已经很好了,比能够自托管的选项都要成熟不少。

不过剩下的我也没什么好讲的了,如果你决定自托管,那就选择一个自己觉得不错的接收端软件部署到服务器上。至于如何查看接收到的 Webmention 和如何展示,不同的接收端都有实现细节上的不同,这里略过。

如何制作一个 Webmention 表单?

还记得我们说发送 Webmention 就是发送一个 POST 请求吗?想想还有什么是 POST 请求?一个网页上能够发送 POST 请求的最常见的元素是什么?

没错,就是表单。

<form action="https://alice.blog/webmenion" method="POST">
 <input type="url" name="source">
 <input type="hidden" name="target" value="{{ .Permalink }}">
 <button type="submit">发送</button>
</form>

其中:

  • action 是 POST 请求要发送到的地方,这里填写你的 Webmention 端点
  • <input name="source"> 是用户输入的,对方文章的 URL
  • <input name="target"> 是你这篇文章的 URL,一般由程序自动生成;这里写的 {{ .Permalink }} 是 Hugo 的页面永久链接,你应该把它替换成你的博客软件的变量。

你需要改的就只是 action 的地址和 <input name="target">value,不需要写 JavaScript。不过,用户点击提交之后会被直接传送到 action 所指向的地址,如果你的 Webmention 接收端只返回 JSON,用户可能就不清楚到底有没有提交成功,还是有些不太友好的。如果你愿意的话,可以自己用 JavaScript 处理返回的数据,制作直观的提示,比如「发送成功」之类的。

放一个这样的表单在网页上并说明清楚作用,即便是不了解 Webmention 的访客也懂得如何使用。

让 Webmention 生动起来:microformats

microformats 是一系列开放数据格式,建立在已被广泛采用的标准之上(比如 HTML)。它并不是和 Webmention 强绑定的,实际上 Webmention 标准完全没有提到过 microformats,只不过 IndieWeb 上的人很喜欢把它和 Webmention 一起用。说起来,应该是 webmention.io 的维护者 Aaron Parecki 带的头,webmention.io 默认支持解析 microformats。

由于没有 microformats 也不影响使用 Webmention,如果你不感兴趣的话,可以跳过这一节。

microformats 是什么?

回答这个问题之前,先要了解它解决了什么问题。

网页可以是任何东西,可以是 Web 应用(比如 Notion 这样的在线笔记),可以是小工具(比如计算器、格式化工具、视频下载器),可以是相册,也可以是一篇文章,可以是日历。同一张网页也可能包含各种各样的东西,一篇博客文章中有页面标题、主体内容、标签、评分、回复等等。

网页的具体结构也是不确定的,为了实现不同的排版和效果,不同网站的 HTML 结构完全不同。有的可能是这样的:

<main id="container">
 <h1 id="post-title">Title</h1>
 <article id="post-content">
 <p>Content</p>
 <!-- ... -->
 <p>Author is ..., follow me on <a href="https://mastodon.social/@author">Mastodon</a></p>
 </article>
 <div id="comment">
 <!-- ... -->
 </div>
</main>

也有可能是这样的:

<main id="container" class="flex justify-center items-center my-10 mx-auto p-4">
 <header class="max-h-lg shadow-lg">
 <div class="rd overflow-hidden">
 <img src="/posts/xxx/banner.jpg" class="block">
 </div>
 <h1 class="font-extrabold text-3xl">Title</h1>
 <p class="font-semibold text-xl">Subtitle</p>
 </header>
 <article class="text-md leading-loose prose">
 <div id="post-content">
 <!-- ... -->
 </div>
 <div id="post-endnotes">
 <ul>
 <!-- ... -->
 </ul>
 </div>
 <div id="author-info" class="bg-white px-4 py-6 my-2 shadow">
 <p>Author Name</p>
 <p>Description</p>
 <a href="https://mastodon.social/@author">Mastodon</a>
 </div>
 </article>
 <footer>
 <!-- ... -->
 </footer>
</main>

偶尔还能见到一些莫名其妙的 HTML 结构,比如我就见过这样的:

<div id="scroll-body">
 <div id="contant-wrap-wrap">
 <div id="content-wrap">
 <div id="main-content">
 <div id="page-content">
 <h1 id="page-title">...</h1>
 <p>...</p>
 </div>
 </div>
 </div>
 </div>
</div>

简直有大病。 无论如何,尽管它们的结构不同,但包含的内容是相似的,换句话说,数据结构是相似的。他们都有可能是一篇文章,包含页面标题、内容、作者信息等等,这篇内容同时还有可能是另一篇内容的回应、点赞或转发。

被浏览器渲染为图形过后,人读起来会理所应当地觉得这些就是相同的数据,但在机器看来就难了。HTML 结构有无限种可能,要怎么让机器快速且准确地判断某个网页属于什么类型的内容,它包含了哪些结构化的数据?

其实已经有一些方案被提出了,比如被广泛使用的 Open Graph 协议 。网页只要按照标准,添加一些 <meta> 标签,就可以使其成为一个数据对象。Facebook 等社交媒体,在遇到这些链接的时候,会爬取 Open Graph 的内容,生成更具视觉效果的卡片。

以下是 Open Graph 的一个例子:

<meta property="og:title" content="The Rock" />
<meta property="og:type" content="video.movie" />
<meta property="og:url" content="https://www.imdb.com/title/tt0117500/" />
<meta property="og:image" content="https://ia.media-imdb.com/images/rock.jpg" />

microformats 是类似的东西,但他没有规定新的 <meta> 标签类型,也不像另一个标准 JSON-LD 一样要求插入一大段包含 JSON 的 <script> 标签。它就建立在最基础的 HTML 之上。

以下是用 microformats 标记的一篇博客文章示例。

<article class="h-entry">
 <h1 class="p-name">Microformats are amazing</h1>
 <p>Published by <a class="p-author h-card" href="http://example.com">W. Developer</a>
 on <time class="dt-published" datetime="2013-06-13 12:00:00">13<sup>th</sup> June 2013</time></p>

 <p class="p-summary">In which I extoll the virtues of using microformats.</p>

 <div class="e-content">
 <p>Blah blah blah</p>
 </div>
</article>

注意到 class 的值了吗?p-name 标记了这篇博客文章的名字,p-author 标记了作者,p-summary 标记了这篇文章的总结摘要,e-content 则是这篇文章的内容。最外层的 h-entry,标记这是一个条目,博客文章、社交媒体发帖和维基页面等等,都可以用这个类名标记。

要实现 microformats 标准,你不需要在其他地方添加任何别的格式的数据,只需要在原有的 HTML 上操作就好了。刚刚我们看到的是 h-entry 格式,用来标记发布在万维网上的内容,除此之外,还有用来标记人和组织的 h-card ,用来标记日历和事件的 h-event 等等。

我们刚才用来配置 IndieAuth 的 <link rel="me"> 标签,也是一个 microformats 格式 。它更常见的用法是直接标记在 <a> 标签上:

<a href="https://github.com/tantek" rel="me">@t</a>
<a href="https://tantek.com/" rel="me">https://tantek.com/</a>

rel="me" 本身不是用来配置 IndieAuth 的,只是标记网站站长的其他网页链接的一种方式。IndieAuth 只是使用了 microformats 的这个格式而已。

总而言之,microformats 是名副其实的「微格式」,不需要对网站结构做出太大改动,就可以标记结构化的数据。

和 Webmention 的关系

我猜测除了 webmention.io 之外,没有太多接收端实现了解析 microformats 的能力(不过, Weepinbell 可以!)。最初 Webmention 仅仅是「A 网页提及了 B 网页」的通知,并没有什么复杂的分类,但 microformats 的使用让一切都不简单了起来。

一般来说,相互提及的网页都是博客文章,文章是用 microformats 的 h-entry 标记的。这个格式除了标记基本的元信息之外,还有这样的属性:

  • u-in-reply-to:这个 h-entry 回复了哪篇文章
  • p-rsvp:这个 h-entry 是对什么的 RSVP,即表明自己是否要参与某次聚会、活动或事件
  • u-like-of:这个 h-entry 是对哪篇文章的喜欢(点赞)
  • u-repost-of:这个 h-entry 是对哪篇文章的转发

比如,Bob 回应了 Alice 的文章,它在文档开头提及了 Alice 的文章,它可能是这样写的:

<div class="h-entry">
 <h1 class="p-name">对 Alice 文章的回复</h1>
 <div class="e-content">
 <p>前几天我在 Alice 的博客上读到了
 <a class="u-in-reply-to" href="https://alice.blog/">
 一篇有趣的文章
 </a>,
 我很受启发。</p>
 <p>对这个问题,我也有相似的思考。</p>
 <!-- ... -->
 </div>
</div>

你注意到了吗?Bob 把文章中提及的链接标记为 u-in-reply-to。如此一来,这篇文章在能够解析 microformats 的程序看来,就是对 Alice 文章的一篇回应。如果是 u-like-of,就是对那篇文章的点赞,u-repost-of 就是转发。

至于 p-rsvp,我觉得这个设计有点大病——真的会有人写网页公开发 RSVP 吗?这种东西难道不应该私下交流吗?无论如何,它是存在的,你可以用 microformats 标记 RSVP,也意味着你可以用 Webmention 来发 RSVP 通知他人你是否决定出席某次活动。

具体而言,Webmention 和 microformats 这两个标准是这样一起使用的:支持解析 microformats 的 Webmention 接收端,在收到请求时,除了做最基本的检查之外,还会解析 source 网页中的 microformats,如果有的话,就一起保存下来。

IndieWeb 上的居民会根据 h-entry 是否包含 u-in-reply-to 等属性,决定展示 Webmention 的方式。如果有 u-in-reply-to,就显示为回复或评论;如果有 u-like-of,就显示为点赞;如果有 u-repost-of,就显示为转发。以下是 Barnaby Walters 的网站实现这一展示方式的例子。

Barnaby 的 网站

如果都没有,那就当作普通的提及,也就是最原始的 Webmention。

在 Webmention 中显示自己的名字和头像

上一小节解释了 h-entry 格式,用来标记内容。用来标记作者时,可以用到 h-card 格式。

<a class="h-card" href="https://tantek.com/">Tantek Çelik</a>,

<span class="h-card">
 <a class="p-name p-org u-url" href="https://microformats.org/">microformats.org</a>
</span>

h-card 本来是独立的,用来标记人和组织的格式,但它也可以作为 h-entry 的子属性 p-author,放在 h-entry 里,标记这个内容的作者。

<div class="h-entry">
 <div class="p-author h-card">
 <img src="https://aaronpk.com/images/aaronpk.jpg" class="u-photo" width="40">
 <a href="https://aaronpk.com/" class="u-url p-name">Aaron Parecki</a>
 </div>
</div>

这样,其他软件在解析 microformats 的时候,就能发现你的名字和头像了。一般来说也会展示在 Webmention 里。

同步来自联邦宇宙的提及

你可能怀疑会不会真的有人这样用 microformats,给链接标记 u-in-reply-to 这样的类名总归有点麻烦,大部分时候我们只是简单提及一篇文章而已,不见得就是对那篇文章的直接回应,或者说点赞和转发。这些东西更像是社交媒体上会用到的。

嗯?社交媒体?

既然我们在讨论开放的标准,那就不得不提及开放且去中心化的社交媒体了。是的,我说的就是 联邦宇宙 。有没有办法把来自联邦宇宙的点赞、回复和转发,以 Webmention 的方式同步到网站上呢?

答案是使用 Brid.gy ,这个服务允许你用 Mastodon 账号(以及其他兼容 Mastodon API 的联邦宇宙软件)登录,并将社交媒体账号与你的网站桥接起来。它做的事情很简单:

  1. 每隔一段时间扫描你的社交媒体时间线,以及其他人与你的互动。
  2. 如果发现你的某篇帖文包含你的网站上的 URL,而又有人点赞、回复或转发了这篇帖文,那么就视作这个人点赞、回复或转发了你网站上对应的这篇文章。
  3. 创建一个占位 HTML 页面,包含用 microformats 标记的 h-entry,以这个占位页面作为 source,给你网站上的页面发送 Webmention。(如果你直接访问这个占位页面,会被跳转到实际的联邦宇宙帖子,但 Webmention 接收器会把这个占位页面视作真实的 source 地址)

如此一来,你的网站就通过 Webmention 和联邦宇宙互通了。

Bridgy 的后台,列出了联邦宇宙上的互动,其中的一些已经作为 Webmention 发送

我的网站就是这样做的,拉到页面最下方,你就能看到来自联邦宇宙的点赞和回应,不过我还没想好应该如何展示「转发」这个类型的 Webmention。

自己动手写 Webmention 接收端

自己写 Webmention 接收器并不困难!你只需要把 Webmention 文档 中有关接收端的部分读一遍,知道需要注意哪些技术细节12就好了。你只需要提供一个用于接收 Webmention 的端点,至于查询 Webmention 的 API,以及要不要解析和储存 microformats,都可以自己决定。

你完全可以只写一个给自己用的 Webmention 接收端,接收到 Webmention 请求后就通过聊天机器人发送给自己,不做展示也不做过多的处理,甚至不用储存。Webmention 尽管有规定删除和更新 Webmention 的方法(如果 source 有更新或者删除了引用,重新发送一次 Webmention 就应该能够更新),但并没有说一定要储存和展示 Webmention。

你也可以把 Webmention 的功能做得很丰富,用来代替评论系统。无论如何,如果你决定自己写 Webmention 接收端的话,这都取决于你,只要保持最基础的标准就好了。

你也可以看看 Salmention ,比起 Webmention,它只是增加了多级回应的功能。比如 Chris 看到 Bob 回应 Alice 的文章之后,也写了一篇文章回应 Bob,并给 Bob 发送了 Salmention。如果 Alice 的网站也支持 Salmention 的话,Alice 就会收到 Chris 的 Salmention,尽管 Chris 只是直接提及了 Bob。不过,这个拓展标准很少有人用。

资源

相关阅读

工具

最后

希望有更多的人能用上 Webmention,一起愉快地写博客交流。

我写累了,一会儿见吧。


  1. 比如,W3C 规定,为了避免 DoS 攻击,所有的 Webmention 必须异步处理,也就是验证 sourcetarget 都是正确的 URL 之后,应该异步地向 source 发送 GET 请求,检查 source 的内容是否包含 target。 ↩︎

  2. 顺带一提,Webmention 其实不止支持 HTML,还可以提及 JSON 文档和纯文本文档。不过,虽然标准是这么写的,但应该不会有太多接收端很好地支持非 HTML 文档。 ↩︎

稻草人周刊 Vol.71

Voicenotes music cover

Voicenotes

Charlie Puth

《Voicenotes》是 Charlie Puth 的第二张录音室专辑,2018 年的热单《Attention》就出自这张专辑。最近在找几年前的专辑来听,走路和跑步时常听这一张。我很喜欢 Charlie Puth 的风格,不过我缺乏基本的乐理知识,不知道从何说起了。这张专辑里我最喜欢的歌曲其实是第一首《The Way I Am》。

I’ma tell ’em all

I’ma tell ’em all that you could either hate me or love me

But that’s just the way I am

顺带一提,Charlie Puth 的下一张专辑《Whatever’s Clever》在本月底就要发行了。我想在这里引用 Taylor Swift 歌曲里的一句歌词:

Charlie Puth should be a bigger artist。1

就这样,继续看周刊吧。如果不麻烦的话,还请留意这一期的「当下」栏目。


连接

程序员如何沟通?

📜

NetNewsWire (macOS 和 iOS 上的自由且开源的 RSS 阅读器)的开发者 Brent Simmons 尝试向亲友解释他的工作,我很喜欢文中的某些句子:

I know I’m a big nerd and what I do must seem all super nerdy and vague.
我知道我是个大书呆子,我做的事情一定看起来超级书呆子,让人看不明白。

My blog inessential.com (this site) has been going since 1999. I mostly write about Apple nerd stuff. Other Apple nerds read it.
我的博客 inessential.com(这个网站)从 1999 年就开始写了。我主要写 Apple 书呆子相关的东西。其他的 Apple 书呆子会读。

In the Apple nerd world I’m the NetNewsWire guy.
在 Apple 书呆子们的世界里我就是 NetNewsWire 哥。

So I’m a nerd and a computer programmer. But what I am not is a math nerd… I’m usually the worst person at math in any room I’m in. Shock, I know!
对,我是个书呆子,是个程序员。但我绝对不是数学书呆子…… 我在任何地方通常都是那个数学最差的人。令人震惊,对吧!?

好了,对 nerd 这个词的滥用我们看够了。读完之后我突然觉得 Brent 变得很亲切,因为我和他一样,数学非常差劲!虽然有些难以启齿,但仔细想想也没什么好隐瞒的:我的高考数学成绩只有 68 分!Brent 说他没有大学毕业,但就算毕业了,也会得到英语学位,而不是数学学位。

似乎全世界都有这样的误解:程序员一定数学很好,要学编程一定要先学好数学。我记得我的初中老师就问过我:“你学这个编程,难道不需要把数学学好吗?”

他关于软件开发的观点我很喜欢,他认为编程的重点不是数学,而是沟通。首先是程序员和机器的沟通,更重要地,如果你在开发一个 App,也要考虑如何设计软件,让软件更好地和用户沟通。我在学软件工程相关的课程,例如需求工程、软件项目管理和架构设计的时候,也逐渐意识到,软件开发中最重要的过程从来不是写代码,而是沟通。架构设计是一种沟通、需求获取是一种沟通,更别提开发团队内部的沟通和与用户的沟通了——这也是我不担心程序员会被 LLM 取代的原因。

Like any other popular art form, it’s about connecting with humans.
就和其他流行的艺术形式一样,重点在于和人的链接。

我想我比起后端更喜欢前端开发的原因也是如此,前端与用户的链接感会更强。不过从技术上,我还是不太喜欢 JavaScript 生态。记得去年还有过学 Swift 做苹果开发的想法,兴许最近也可以捡起来了,先等水逆过去吧。

擦马桶如何帮我维持学者风范?

📻

听这期博客的前几天才刷过马桶,亮到能反光。于是我一边把洗手间的各个角落刷了一遍,一边把这期播客听了两遍。我最喜欢的句子是:

在网上喷粪不如在现实中擦粪。

树老师说他不焦虑、不想死,是因为每天都要做家务,没空想东想西。整天坐在电脑前从事思考工作的人容易产生这样一种假象,认为一切都在控制当中,然而当生活中的小事出了差错,这种差错很容易降他们击垮,陷入崩溃当中。我也赞同,在网络世界、精神世界、知识世界中待久了,需要关注现实,而且是与自己有着直接关联的现实,而非别人的生活、海另一边的战争、某个无聊的家伙对自己的谩骂。

刚打开这期播客没多久,我就做了一个决定。我找到我的室友,告诉他以后的家务都由我来做。这里要交代一个背景:先前我们是按照时间来划分家务职责的,一个人负责一天,但他老是忘记,我也常因为各种小事跳过自己做家务的那一天;最近改成了按照事务划分,每个人负责一部分,当时厕所划分给了我,与是我立马把马桶擦得锃亮给他打了个样,可惜激励效果欠佳。某天我看不下去,自己动手吸尘拖地(这本该是他负责的工作)。于是我想,比起每天阴湿地暗暗谩骂对方不好好做家务,不如自己把活儿全干了。我告诉他接下来的家务我全包了之后,他还有些尴尬地回应说自己最近太忙了。

我最近也没闲着,野心勃勃地同时推进着两个个人项目,学校那边也有各种琐事,辅导员和某些老师也在推着我做职业规划,焦虑是难免的。正是因此,我才开始比以往更加频繁、细致地做家务,把自己的大脑从想东想西的状态拉出来,开始关注身体、生活环境和秩序。

所以,读者有没有什么瓷砖和木地板的清洁剂推荐呢?

亚当·斯密如何颠覆古典美德?

📻

赵老师的讲话方式指定跟树老师学了不少。

播客前半部分阐述了亚当·斯密(《国富论》的作者,现代经济学之父)的生平和轶闻,后半部分进入正题,讲述亚当·斯密眼中现代社会应有的美德,与古典美德有何不同,以及他对于古典美德的观点。

美德在拉丁语中写作 virtus,也就是如今英语里的 virtue,这个词的词根 vir 意思是「男人」,拉丁语中美德的本意是 manliness,可以译作「男子气概」。古希腊语中的美德 ἀρετή 也是类似的意思。谈到古典美德,一般会说到柏拉图的四个枢德,即节制、审慎、勇气和正义2,其中勇气是最重要的。相对的,温柔等特质在古典语境下通常与女性联系起来。简单来说,在古希腊人和古罗马人看来,最勇猛的战士就是最具美德的人。

亚当·斯密认为,古典美德所强调的男子气概是野蛮的、原始的、落后的,现代社会所需要的美德应该是具有同理心(sympathy)的美德,即设身处地为他人着想。在古典美德中,美德有高低贵贱之分,而且往往是生来就具有或者没有的,比如贵族的美德就要比奴隶的美德更高;而亚当·斯密认为的美德是人人都能够获得的,是在社会交往中通过反思获得的。简单来说,亚当·斯密的美德是一种更温顺的美德,如果说古典美德实际上是男人的美德,那么亚当·斯密的美德就更接近女人的美德。不过,亚当·斯密所言的同理心其实和大多数人理解的意思也有差异,比如,他认为和商贩交易也是同理心的体现,因为顾客设身处地为对方着想,提供了对方所需要的东西;再比如,他认为富人和快乐的人更容易引发同理心,而不是穷人和悲伤的人。

对于这两种美德,也可以联系到第 42 期周刊引用的 古典审美与现代审丑 。在我看来,古典美德在如今的视角下更接近于自我要求,而强调同理心的现代美德更接近于社会要求。个体可以要求自身节制,比如节制饮食,但在社会层面,应该对肥胖者有同理心,不去责备他们缺乏节制的美德。3

锻炼是为了什么?

📻

树老师在这期运动闲聊播客里分享了她母亲的锻炼心态,她认为她母亲的心态要比她自己和许多年轻人都健康不少。她的母亲在过去的几十年人生里都没有任何运动习惯,直到年过五十,发现身体正在明显地衰老、恶化,才开始为了维持生命而运动。她锻炼的目的是为了对抗衰老和掌控身体,是为了锻炼神经系统调动身体部位的能力,每天能动起来她就很快乐了。

对比另一种锻炼心态,追求进步、对比和竞争的锻炼,「快乐老女人」的锻炼心态要更健康。前者容易陷入这样的窘境:一旦做不到进步,或者进步不够明显,锻炼的乐趣和动力就会大大减少;一旦有了对比,锻炼的目的就不再是满足自己身体的需求,而是为了迎合别人的审视;一旦有了竞争,人就会感到焦虑。这种锻炼心态甚至成为了门槛,让没有锻炼习惯的人认为,自己要是没有运动天赋,就不该开始运动。实际上,每天都让自己动起来这个事实本身就值得骄傲,就像自己又活了一天一样值得庆祝。

关于锻炼的目的,我的观点可以引用 Steven Pressfield 的《 一生之敌 》中的一句话来阐释:除了爱,出于任何其他原因而从事艺术创作,都是卖淫。 把这句话的「从事艺术创作」换成「锻炼」,就是我的观点,而且我觉得这句话用在「身体」相关的话题上,显得更有说服力。

锻炼是为了保证身体的机能,提升神经适应性,保证自己的身体能做到它应该做到的事情。简单来说,是为了健康,而对健康的追求就是对生命的热爱——我那个经常跑健身房,买五花八门运动补剂,没事就对着镜子拗造型的室友,还对我这个目的颇有微词。 我向来很欣赏热爱力量训练并关注身体变化的人,不过我欣赏的是能从训练和身体变化本身得到满足的人。

更准确地说,我欣赏所有好好为自己和自己热爱的事情活着的人,在我看来,这才是生命力的体现,而生命本身就是意义。

星群

GRAM

Zed 的分支,托管在 Codeberg 上,移除了服务条款和 AI 功能,是纯粹的自由软件,也是纯粹的编辑器。Zed 和 GRAM 是用 Rust 语言编写的 VS Code 替代品,换用 Neovim 之前我一直在使用 Zed,至少在 macOS 上启动速度很快,界面也很干净,是我很喜欢的用户界面风格。

不过 Zed 并不是纯粹的自由软件,因为它有 服务条款 ,还有付费的 AI 功能,是开源的商业软件。最近 Hacker News 上还有有关 Zed 的小 讨论 ,因为 Zed 在服务条款里增加了年龄要求,不过并不是威胁隐私的年龄「验证」,相关内容见 我的帖文 。尽管本体是 GPL 协议,但项目的 README 下赫然写着:

Zed is developed by Zed Industries, Inc., a for-profit company.

那就不能指望挣钱的企业抛弃讨厌的 AI 功能了。GPL 协议的好处就是自由,可以随意更改和分发软件,于是一个移除了服务条款和 AI 功能的 Zed 编辑器就诞生了!也不知道我这个 Neovim 用户在激动什么。

如果你在找 VS Code 替代品4,GRAM 值得一试。

访问: GRAMCodeberg 仓库

blogtato

用 Rust 编写,基于命令行的 RSS 阅读器,无需订阅,本地优先,而且支持使用 Git 同步数据。不过说是阅读器,其实更像是 RSS 更新提示器。这对我来说更好,我一直不太喜欢直接在 NetNewsWire 里阅读文章,更喜欢到源网站上阅读。

blogtato 的操作很简单:

# 添加 RSS/Atom 源,blogtato 会自动搜寻订阅源的具体地址
blog feed add https://www.geedea.pro/

# 同步更新,除非执行这个命令,否则 blogtato 不会发送网络请求
# 也不会占用除存除外的任何系统资源
blog sync

# 查看更新
blog

# 在默认浏览器打开编号为 x 的文章
blog x open

还提供了一些好用的筛选和分组功能:

# 按日期、周或订阅源分组
blog /d
blog /w
blog /f

# 合并分组
blog /d /f

# 按照订阅源筛选
blog @hn

# 按照阅读状态筛选
blog .unread
blog .read
blog .all

# 按时间筛选
blog 1w..
blog 3m..1m
blog /d 2w..1w

# 合并筛选和分组
blog @hn .unread /d

blogtato 原生支持 Git 同步,采用无冲突的设计,同步数据时无需担忧 Git 冲突,数据全部以 JSONL5 存储在本地。

我很喜欢 blogtato 的设计理念,我一两个月前也有用命令行做一个 RSS 阅读器或者书签管理器的想法,但一直没有去实现,没想到这几天就在 Hacker News 上看到有人做出来了。可惜目前还不支持导入和导出 OPML 格式,于是我跟作者提了 Issue ,很快收到了回复。对方表示写一个 Shell 脚本导入也不难(毕竟是命令行工具),但其实项目里已经有解析 XML 的依赖项了,所以作为 blogtato 本身的功能加上也没有什么成本,他说他会看看。很期待更新!

我前几天还在联邦宇宙上吐槽,有了 AeroSpaceVimium 插件之后,我的日常操作都可以用 Vim 键位完成,可惜每次查看 RSS 更新的时候,都苦于 NetNewsWire 不支持用 jk 上下移动。blogtato 至少能保证我的手不用离开键盘。

访问: kantord/blogtato

当下

不出意外的话,这应该是《稻草人周刊》里最后一次出现「当下」这个栏目,原因是我正在计划每月更新的新闻报,也就是「Newsletter」,名字暂时还没有定下来。新闻报中计划包含这些内容:

  1. 过去一个月里,自认为写得不错的博客文章(其实《稻草人周刊》也有「回拨」这个栏目,原本打算每个月写一次,但总是忘记,干脆放到月刊里)
  2. 正在进行或已经完成的项目,情况以及进度回报(我对「项目」的定义很广泛,一般来说是软件项目,也可以是目标明确且耗时较长的大任务,比如「把家里的所有塑料制品都替换掉」)
  3. 书影音游回顾,包含这个月看的剧、写过的书评合集和完整听过的专辑等(也希望能借此治好我的电子阳痿吧)

这意味着《稻草人周刊》会更关注于分享我每周读到的有趣文章、听过的觉得有启发的播客、发现的觉得不错的项目。如果你关心我最近做了什么事情,可以等待新的月刊,预计会在四月初发布第一期;或者,你可以在 联邦宇宙 上关注我,可以用 Mastodon、Misskey、Pleroma 等联邦宇宙软件与我社交。

切片

  • 状态低迷、注意力涣散和效率低下的状态持续挺久了,春节结束回到家也不见好转,遂求助玄学,盘了半天月运势和周运势也没看出个名堂,直到突然被提醒天象:从二月底开始水星逆行了,直到三月 20 日结束。

    水逆啊,那不稀奇了,放心躺吧。

    双子座加月升处女已经被水逆折磨习惯了

  • 夜里睡不着,爬起来看手机,很奇怪,根据我的经验,刷信息流实际上能让我更容易入睡,因为大脑会很快感到疲惫。疲惫之前,看到了 Minecraft 26.1 版本的更新,给所有生物都增加了幼年形态,很可爱。

    还有史诗级的更新,命名牌可以用纸和铁粒(以及金粒和铜粒)合成了!钓鱼和开箱子找命名牌的时代结束了!虽然是很好的更新,但总觉得有些失落——原来现在 Minecraft 里的命名牌已经不是稀奇的事物了啊。

    有些怀念以前的游戏时光,好久没有畅快地和朋友玩一下午 Minecraft 或者饥荒了。想拉拢几个人来,搭一个 Minecraft 服务器,也不知道能不能找到人,或者说自己能不能抽出时间。

    周刊的最后,给各位看看我几年前自己画的 Minecraft 皮肤吧。

    原来那个时候我就开始用考拉当身份标识了吗?

    除了 Vanila 和 Migrator,其他披风我都不知道怎么来的


  1. 出自《The Tortured Poets’ Department》 ↩︎

  2. 参见: 美德 - Wikipedia  ↩︎

  3. 相关博客文章:《 关于肥胖的杂谈 》 ↩︎

  4. 是时候抛弃这个基于 Electron 的软件,停止用浏览器编辑代码了 ↩︎

  5. JSONL 是 JSON Lines 的意思,是每行都是一个有效的 JSON 对象的存储格式,可以理解为把一个 JSON 数组写入文件,但是没有前后的 []。 ↩︎

极客死亡计划书 V

在周末打开终端,cd 进极客死亡计划的项目目录,然后打开 Neovim 开始在自己的代码里到处晃悠,删删改改,对我而言是很放松的体验。我时常在浏览器里注意到某个网页元素,回忆起源代码的位置,立马打开编辑器看看有没有需要去毛球(lint)的地方。这种感觉,其实很像是园丁在自己的花园里闲逛,做些简单的修枝剪叶吧?

总之,某个寻常的周末,我冲了一杯非常好喝的瑰夏,在书桌前坐下,开始在代码之间漫游,发觉修枝剪叶的工作都做完了,此时,一个积压在脑后已久的想法突然涌现。我拿起铲子,盯着其中两个花圃,兴致勃勃地说道:“好,那就开始铲土,重新想象园林设计吧!”——这两个花圃就是 前不久 才被移植过的「议论」和「散文」。是的,我把他们又合并了。


用词说明

为了避免误解,我们先理清一些术语。

下文的「分区」指 Hugo 的 section ,也就是顶层的内容目录,比如 /posts 下有 /posts/xxx/post/yyy 等页面,这个 /posts 就是一个分区。

「分类」是指 Hugo 的 taxonomy ,本站有两种分类,一是「 文章系列 」,二是「 标签 」。不过,出于一些历史原因(其实就是我懒得改),「文章系列」这个分类的代码写作 categories,本意是分类。


命途多舛的极客死亡大地

最初,极客死亡计划上只有一个内容分区,即 /posts 分区,所有的文章都放在这下面,其他的页面是如 /about/linkroll 这样的顶层页面。那是段纯真简单的时光,直到某个名叫 Eltrac 的疯子突然决定要把自己写的垃圾小说都搬过来,于是网站上就多了一个 /fictions 分区。

骇人听闻的事件没有停止,这个疯子决定要给自己读过的每一本书在网站上留一个位置。他先对 稻草人 下了手,心狠手辣地把「书评」分区从周刊手里夺走了,把那些残缺的短评放进了他引以为傲的、单独的 Markdown 文件里,大喊着「原子性!」「双向链接!」的口号,使用名为短代码的邪恶武器将书评嵌入了稻草人的身体里,随后又在他飘忽不定的思绪影响下,把那短代码从整个奥兹国代码库里剥去。由于操作习惯拙劣,Git 历史的可读性极低,他的罪行也就没有留下证据,那些被他摧残的文件都改了名,或者进了垃圾桶,连 git blame 的机会都没有!

简而言之,极客死亡计划又多了一个 /library 分区,纯真简单的小骷髅就这么被知识玷污了,眼神里失去了光!

这便是「议叙文大分裂事变」的历史背景,在那之后,Eltrac 短暂地休息了一会儿,可没过多久,他便又舞起键盘,对网站历史最悠久的古迹下了狠手。一向忠心耿耿 /posts 分区被他无情地斩成两半,有超过半数的页面作为 /essays 分区的新臣民被分离了出去,就这样背井离乡。大魔头对此的辩解是:

你也可以理解为,我把文章分成了 T 和 F 两部分(仔细想想,其实更像是 J 和 P 的两部分,判断和感知的区分)。做这个拆分是因为,我发现自己的 T 和 F 可能会在某个时间段宕机其中一个,把这个分开能让我更安心地在情绪崩溃时发疯、在好奇心超负荷运转时写一写没人关心的新话题。

——《 稻草人周刊 Vol.57

何其可悲!何其可悲!仅仅是因为他自己沉迷于愚蠢的大众心理学理论(MBTI),就祸害了全体网站公民的身心健康!更不用说,此举损人不利己,如今大魔头每次在写作时,都会纠结要把他拙劣的文字放在哪边,/essays/posts 说起来有别,但实际上本是同源,都是他那扭曲头脑不能停止转动的产物。不过,我们也不要太苛责这个敌人,毕竟他自己也尝到了苦头,那便是永远不能停止分类和修整的痛苦,如西西弗斯一般永世不能停下!别听那个叫加缪的老头儿乱说,天天推石头可不幸福!

终于,感谢上天的宽恕,误入迷途的魔头 Eltrac 得到了分类之神 cartlE 的指点。cartlE 刚莅临网站,就立刻发觉稻草人不应与 /posts 的子民待在一起。看着 Eltrac 在代码里给稻草人周刊写下的各种特例,神明 cartlE 皱起了眉头,发出疑问:“你是在解鸡兔同笼问题吗?把鸡放鸡笼里,兔放兔笼里不行吗?”

于是,/posts/weekly 从极客死亡计划的土地上消失了,取而代之的,是新成立的 /weekly。天下苦稻草人周刊久矣!为了恕罪,也向 cartlE 神明展示自己的悔意,Eltrac 立马给稻草人修好了 黄砖路 ,供他自由通行。

很快,高明的 cartlE 发现了 /posts/essays 之间的裂谷,便命信息与沟通之神墨丘利去唤来双子座,让它用蟒蛇架起桥梁,把两块大陆合二为一了。终于,失散已久的家人又重聚了,现在 /posts/essays 不再分裂,他们有了共同的新名字——/article。墨丘利还提议,尽管两个大陆合二为一,但旧的居民仍然保留旧的地址,避免书信不能送达,尤其是来自联邦宇宙和万维网提及的消息。1新的居民以 /article/xxx 为地址,而旧的居民仍然保留 /essays/xxx/posts/xxx 的地址。

为了展示自己真的回心转意,大魔王 Eltrac 主动提出,应该把 /fictions 分区更名为 /fiction,因为目前的其他分区分别是 /article /weekly/library,只留一个复数形式的名字有些眨眼。神明 cartlE 听完,满意地离去了,并留下秘籍供 Eltrac 学习良好 Git commit 习惯的艺术。

就这样,暮光闪闪和他的小伙伴们终于让混沌之王无序痛改前非,懂得了友谊的魔力,小马国又恢复到了祥和之中。

等等,你串台到哪儿去了?

ESC to Reality

我的天哪,究竟是什么样的读者才能读懂上面那一大坨自我意识过剩的产物……

让我按下 Escape 键(指切换为 Neovim 的 NORMAL MODE,正常模式),来认真解释一下极客死亡计划目前的内容分类设计。

首先,博客目前只有四个分区:

  1. 文章 :一般来说,我突然想写点什么东西发出来,都会放在这。
  2. 周刊 :每周一更新的刊物,包含这周读到的有趣的文章、听到的播客和发现的不错的项目等等,是我整理和收集信息的地方。
  3. 书目 :我读完一本书都会写书评放在这里。
  4. 虚构 :我写的各类小说。

其他分区几乎都是不言自明的,只有「文章」需要特别说明。正如《命途多舛的极客死亡大地》一节中所述,这个分区原本是 /posts,一开始被称作「议叙」页面,因为它既包含议论文,又包含叙事文和散文。后来,我觉得这两种文体或许需要分开,于是新增了一个 /essays 分区,把议论文都放到这里来。

其实在一开始创建 /essays 分区的时候,我就发现了问题,我很难判断一篇文章的归属,我记得当时我花了一个下午的时间给文章重新分区。这种分区在后来又造就了更多的问题,比如:同一个「文章系列」应不应包含来自两个分区的内容?我有一个文章系列叫《代码炼金术》,这里面可能包含我尝试新技术的经历和感受,重点在于「我做了什么」,写得比较散,应该归为 /posts;而有的时候,我可能发现了一种新的构建软件的方式,比如 用 Lisp 而不是 HTML 写网页 ,这种有深思熟虑且形成可复用的体系的文章,似乎应该归为 /essays。可是,它们都是和写代码相关的,不应该都放到《代码炼金术》这个文章系列里吗?如果一个文章系列里既有议论文,又有记叙文,那不是乱套了吗?

就算不考虑文章系列,确定一篇文章属于 /posts 还是 /essays 也不容易。前者是写「我做了什么」,后者是写「我思考并的出了什么」,实际上有相当一部分文章的写作逻辑是「我做了一件事情,并且借此有了新的思考,产生了新的想法」,那这还要怎么分区?

从盒子里跳出来想问题:给议论文和记叙文分区真的是有必要的吗?

最后我接受了自己的风格就是叙中有议、议中有叙的,于是把两个分区合并到了一起。不过周刊里的东西实在是太杂了,给它单独设立分区会更合理。

Tag, You’re It

你可能会以为,这个前不久还重新装修过 标签文章系列 页面的 Eltrac,又要阴晴不定地把标签和文章系列的其中一个分类给扬掉了,毕竟已经有分区了,再算上这两个分类,网站实际上有三个维度的分类,这太复杂了!

当然,看到「你可能会以为」几个字就知道,我不会这么干。

保留文章系列其实很好理解,保留标签是为了什么?

之前在 Jim Nielsen 的博客上读到过这样的观点:你不需要创建标签,链接就是标签。这里的链接是指在文章中链接到的其他文章,文章之间相互引用所形成的关联,就足够让文章物以类聚了,不需要手动打标签,做额外的分类。这的确是很诱人的想法,所以我给博客做了 视觉化的双向链接图谱 ,然后就把「用链接替代标签」这事抛之脑后了。

不移除标签,首当其中的原因就是,双向链接图谱虽然很酷,但是不方便查询。如果真的要找我写的有关某一主题的文章,到像海一样的双链图谱里去找是低效的,这些文章之间也不一定有超链接关联。

再者,我的博客也不是维基百科。据说从维基百科的某个页面开始,一直点击页面中的第一个超链接前往不同的页面,最终会到达「哲学」这个词条。我添加超链接的习惯不如维基百科编辑者那样专业、审慎和克制,没法做到这么严谨的关联,说实话,也不需要这样严谨。

不过,要说最重要的原因,那还是因为我想要按照主题划分文章。我是个兴趣泛滥者,如果你关注我的博客足够长的时间,就会发现我既谈游戏开发,又谈前端开发,还做命令行工具;我不仅写计算机,还常常观察人类,并写下思考;我不仅对社会学、心理学和经济学这些科学感兴趣,还对文学、哲学和语言学感兴趣,我甚至还探索神秘学,会研究占星和塔罗牌;即便是文学这一个类别,我也会涉猎法国文学、拉美文学、日本推理文学和各种杂七杂八的门类。

五花八门的内容要是不按照主题分类,恐怕读者难以把握脉络,也难以找到自己真正感兴趣的内容。假设一个读者只是因为神秘学而关注我,他就可以去阅读 #神秘学 标签下的内容。标签实际上提供了内容的切片。

此外,并不止是文章,在我的设想里,网站的所有内容都通过标签来归类,而文章系列只是给文章的。如果你打开网站的标签页来看过,就可能发现 #心理学 这个标签下不仅有我写的文章,还有《 被讨厌的勇气 》《 天生不同 》《 如何在黑暗的房间里找到一只猫 》等书籍的书评,实际上小说和周刊也按照标签归类。

网站页面,列出了同一个标签下的所有内容,包括普通的文章、周刊、小说和书籍,这些内容是分开罗列的

#内阻力 标签页的截图,截于 2026 年 3 月 8 日

不过,现实有些残酷,从 GoatCounter 的统计数据来看,几乎就没有访客会点开任何一个标签页面,我设想中的「读者可以按照自己感兴趣的话题查看内容」这个需求用例实际上根本不存在。对我自己而已,我也很少在某天突发奇想「要不要看看自己写过什么和占星有关的文章呢?」,然后点开标签页面查看,对我自己的用处也不大。

所以,为什么要留着标签这个东西呢?管理标签费事费力,为了打标签,每次都要先查看已有的标签,用人眼浏览一遍,看看有没有能对得上的;还要克制住自己新增标签的欲望,避免出现太多只有一两篇文章的孤立标签;更麻烦的是,还要记住各个标签的语义,不能混用。标签也很难体现出层级关系,却在很多场景下不能避免进行细分,比如博客就同时存在「神秘学」「占星」和「塔罗」三个标签,而第一个标签实际上是后两个标签的大类——能不能合并成一个呢?它们真的经常出现。然而,有时候我只是广泛地谈一谈神秘学,比如《 好为人师如何帮我反思现代科学的局限性? 》这篇文章,仅仅是在论述「适当的玄学和迷信为什么是有用的,甚至能达到理性的科学知识达不到的效果」这个观点;有时候,我又是在具体地谈 塔罗牌里某张牌的含义 ,这就没必要打上更宽泛的「神秘学」标签了。2

无论以上这些问题的答案如何,都不能发现,标签的存在本身就引发了许多管理难题,而它带来的实际价值却非常少。很明显,我应该把它删掉。

可我偏不。

为什么?答案其实相当不理性,但也相当具有说服力:我不想把它删掉。我想我可能是喜欢标签体系带来的秩序感,也需要建立和维护秩序的感觉。另外,我总觉得,网站的分类就和图书馆一样,大部分找书的人其实都是找到具体书籍的编号之后,直奔书本所在地,但也不能忽视,有很少的一部分人愿意在某个主题的书架附近漫游,发现从未见过的书本。所以,标签可能大多数时候派不上用场,但对我而言,是不能没有的。

最后

所以,这大概就是新的秩序了。

《极客死亡计划书》系列文章的最后,还是要给下一期留个引子。我正在思考博客的交互设计。一两个月前就有关注我的读者可能有印象,以往博客文章的底部有一个「心脏」按钮,将鼠标移上去,显示的文字是「为这篇文章献上心脏」,点击之后,心脏图标会变红,文字会变为「你已经献上心脏了」。这其实是点赞按钮,任何人都可以点击它,让点赞数量增加 1。并且,读者点赞之后,页面的最下方会出现一整排「已经收集到的心脏」,有多少点赞数就有多少心脏。我印象最深的是,有一篇文章的点赞数量超过了 20,当时页面下面非常壮观。

图片最上方是三个按钮,一个评论按钮、Webmention 按钮和「献上心脏」按钮。心脏的数量是 26,页面下方摆满了人体器官。

旧的文章互动区

可惜,「献上心脏」随着 评论系统的移除 一同消失了,一直没有加回来的原因是,我在纠结如何把本身就有些复杂的新交互区设计得更简洁一些,增加元素不太明智。再者,现在博客本身也会同步来自联邦宇宙的点赞,功能上有些重叠。

不过,我想我大概还是会想办法把「献上心脏」加回来的,因为我的确需要一些实在的反馈,不只是访问统计数据。说实话,现在会在联邦宇宙上点赞和留言的读者不算多,至少我很久没看到点赞的数量超过 10 了。尽管,最健康的态度应该是完全不在乎这些数据,只关注和真实的人建立起的链接,但…… 我想我还需要再思考一下。

以前,网站的标签页面还有一个操作按钮,是一只乌鸦,按下之后会隐藏当前页面下的所有「稻草人周刊」。当时这么设计,是因为稻草人周刊混杂在文章分区内,本身的内容又很杂,容易让人抓不住重点,所以提供了一个筛选功能。当时我还费心设计了动画,把鼠标移动到乌鸦头上,页面里的稻草人周刊链接就会闪烁,点击之后这些链接就会收缩起来,直到消失;再次点击按钮,这些链接又会在入场动画之后出现。由于现在周刊是单独的分区了,没有混杂在文章里,这个按钮也就不再需要了。

这些好的改动,似乎磨灭了一些个性,有些不符合我在《 「极客死亡计划」的设计哲学 》里提到的第八项原则。当时举的例子里,还留下的就只有 404 页面和 Batrick3 了。

这些设计的去留和增改的确需要好好思考一下,不过这就是下期的内容了。

回见!


  1. OK,我知道我有点放飞自我了,所以我暂时脱离精神分裂状态来解释一下,这里说的是:我用 Gemini(双子座)生成了一个 Python(蟒蛇)脚本,让它把两个分区合成一个了,之所以提到墨丘利(Mercury),是因为双子座的守护行星是水星(Mercury)。由于 Webmention 依赖 URL 标识源地址和目标地址,如果改了地址,仅仅作重定向是不够的,会导致旧的 Webmention 失效,除非重新发送一遍,所以就用 Python 脚本给每篇文章都添加了 url 属性,这样就算文件放在 /article/xxx.md 下,URL 也还是 /posts/xxx 或者 /essays/xxx。 ↩︎

  2. 不要建议我用大语言模型自动打标签,如果我不能清楚明白每个标签的具体语义,那做分类还有什么意义?为什么要为了支撑一个已经丧失了意义的事物的存在,而浪费大量的算力? ↩︎

  3. 如果你把页面往上滚动,就会看到一直蝙蝠从页面顶部飞下来,它是「返回顶部按钮」。点击它,Batrick 就会带你上去。 ↩︎

稻草人周刊 Vol.70

The Dark Side of the Moon music cover

The Dark Side of the Moon

Pink Floyd

这是一张上世纪七十年代发行的摇滚专辑,是 Pink Floyd 乐队发行的第八张录音室专辑,名为《月之暗面》。我最喜欢的一首是 Brain Damage(脑损),不过,我建议你一定要从头到尾把专辑听一遍。专辑不长,只有十首歌,一共四十多分钟。这首 Brain Damage 和下一首 Eclipse(日食)连接非常顺滑,让不仔细听的人觉得是同一首歌,整张专辑都用这样的衔接串联了起来,最后以心跳声结束。

And if the dam breaks open many years too soon
如果大坝早了许多年破裂

And if there is no room upon the hill
如果山丘上已经没有位置

And if your head explodes with dark forebodings, too
如果你的头脑也因不详的预感爆开

I’ll see you on the dark side of the moon
我和你会在月之暗面相见

连接

FLOSS 和 FOSS

📜

FLOSS and FOSS by Richard Stallman

如果你不知道这个作者是谁:他开发了 Emacs 编辑器,还编写了 GNU GPL 开源协议,是自由软件基金会的创始人。

本文解释了 FLOSS 和 FOSS 的区别,以及相关术语的政治倾向。简单来说,自由软件社区有两个政治派别:自由软件运动派(free software movement)和开源派(open-source)——这两个概念完全不一样,不应该混淆。自由软件是指可以自由运行、研究、更改,以及分发未更改或更改后副本的软件。开源的概念是后来(1998 年)出现的,一开始是为了避免人们混淆「Free」的意思(可能会被误以为是「免费软件」),不过开源的意思很快发生了改变,与自由软件运动分道扬镳。许多人把开源当成自由软件的商业概念,好让商业公司对自由软件的实用价值(practical benefits)感兴趣,而忽视了「自由」,很快「开源」就变成了强大、可靠软件的代名词,人们对「自由」的关注减少了。

很不幸,我最初接触到的概念就是「开源」,而非「自由软件」。

既然有两派之分,自然也有中立派。中立派使用「自由和开源软件」这个词,即 FOSS(Free and Open-Source Software)。这个词没能解释「Free」的真正含义,所以有人会使用法语或西语单词「Libre」来准确表达「自由」的意思,继而有了 FLOSS(Free/Libre Open-Source Software)这个词。Richard Stallman 在文中表示,自由软件运动的参与者不会使用 FOSS 或 FLOSS,因为这个词把 Free Software 切分开了,把注意力给了 Open-Source;应该使用 Free Software 或者 Libre Software 这个词。

至于我的态度,抛开别的不谈,如果只用言简意赅的程度来评判,我不得不说,「自由软件」是更好的词。此外,FOSS 和 FLOSS 作为缩略词,理解门槛会更高一些,而且中文里还是尽可能少夹杂英文比较好1

被赋予的自由不是自由

📻

播客从女性主义展开,回顾和分析了现代的人权进程,关于「自由选择的权利」。

播客中重要的观点是:被赋予的自由不是自由。一个思想停留在前现代的老妇人,没有自我意识,明明知道自己的丈夫对她不好,甚至恶语相向,却还要求死后跟丈夫葬在一起,并教育子女成为和他一样的受害者。这类人无疑是可怜的,但没有办法被拯救,即便他们在政治层面拥有了自由,他们也无法真正行使自由,甚者,他们根本不觉得自己是自由的,或者完全不会思考「自由」这个概念。

对于受过现代教育的人而言,自由也不见得总是好事。因为自由太广泛,选择的数目太多,人们获得的不是选择自由,而是选择困难。这种选择困难小到购买家电时陷入纠结,难以找到最好的选项;大到面对分叉的人生道路时,因无法在可能性之间做出选择,而荒废宝贵的时间。自由甚至妨碍了人们好好生活。许多人感到焦虑痛苦,就是因为有着无止尽的选择,每天都在为上一个选择而后悔,为下一个选择而纠结。这么看来,陈腐、老旧的生活方式,由于不需要支付选择自由的代价,反而是轻松的人生。

播客并没有给出解决方案,兴许也不会有适用于所有人的解决方案。争取自由(各种意义上的自由)都是要付出代价的,轻松的做法当然是服从长辈、听信权威、享受大科技公司的产品,把选择的代价外包出去,但别忘了,在「自由」和「轻松」之间选择,也需要拥有选择的自由。

永远不要买 .online 域名

📜

作者在 Namecheap 上买了很便宜的 .online 域名,用来做产品的主页,网站上只放了一些介绍,和 App Store 的链接。某天他发现网站被标记为「危险网站」,整个浏览器页面都是红色的,绕过警告强制打开后,发现无法正常访问网站,状态显示 serverHold。排查后发现 DNS 没有解析,原因是这个域名被列进了「安全浏览黑名单」(Safe Browsing blacklist)。

在邮件联系了注册商和注册局之后,作者得知他必须在谷歌搜索控制台(Google Search Console)验证域名所有权,才能申请重审,但这无法做到,因为验证身份需要更新 DNS 记录,而他的域名因为被列入黑名单而根本没有被解析。

所以,教训就是:不要买看起来很奇怪的 TLD。

蠢货相处会变老得更快

📃

这是一篇科学研究,我只读了摘要部分,所以会有疏漏。

简单来说,负面的社会联系(negative social ties)会加速衰老和增加疾病发病率,其中衰老是通过基于 DNA 甲基的衰老生物钟测量的(DNA methylation-based biological aging clocks)。文中把这种负面的社会联系称作 Hassler(纠缠者),并发现研究中 30% 个体都报告他们的社交网络中,至少有一位 Hassler。Hassler 一般占据社交圈的外围,属于弱连接。女性、烟民、不健康者和有着恶劣的童年经历的人,更容易遇到 Hassler,这形成了规律:在社交层面易受攻击(vulnerable)、在健康层面易受病扰的人更容易遇到 Hassler。所以,我猜,如果要尽可能少遇到这类人,应该要变得足够自信和强大才行。

社交网络中每多一个 Hassler,衰老的速度就会增加 1.5%,大概会变老 9 个月。不同的人影响也不同,亲属和非亲属 Hassler 与健康有着有害的联系,而如果伴侣是 Hassler 的话,则没有。如果 Hassler 数量众多,对健康的影响就不只是变老那么简单。

我最近在使用一个 App 分析我锻炼时的「最大摄氧量」,这个 App 会对比同龄人中的平均数据,并计算出我的身体年龄(当然和研究中使用的方法不一样,软件算法也不能和科学研究相提并论)。春节回到家之后,App 计算得出的我的身体情况明显下滑,并表示我正在快速衰老(Aging Quickly),而我刚回到自己家一天,这个数据就开始慢慢回升了。尽管没有太多科学依据,但我觉得这是我远离了一大群 Hassler 导致的,当然还有睡眠的影响,在老家的时候总是睡不好。

星群

互联网电话册

在一个电话界面拨号,就能接通某个个人网站。Internet Phone Book 是每年发布一次的刊物,收录了各种有趣的个人网站,每个网站都有「电话号码」。我是在 Elle 的主页发现这个网站的,他的互联网电话号码是 677

不过我找了半天,也没有找到提交网站的地方,内容兴许都是创始人亲自挑选和收录的吧。

Intert Phone Book: Dial-a-Site

Internet Phone Book 的拨号页面

访问: Internet Phone Book

SplatHash

一个用户生成模糊图片的哈希算法,与 BlurHash 类似,不同的是,这个算法能给任何图片生成固定 16 字节大小的哈希,也可以表示为 22 个字符的 base64 编码字符串,而且,它的解码速度非常快,占用非常小。目前主要提供 Go 语言、TypeScript 和 Python 实现的程序。

这个算法也有缺点,是我的个人观点:生成出来的模糊图片太丑了。

SplatHash 算法结果与 ThumbHash 和 BlurHash 的对比

访问: junevm/splathash

Stop Tahoe Update

Stop Tahoe Update(停止 Tahoe 更新)是由社区维护的项目,帮助不想更新到 macOS Tahoe 的用户留在 Sequoia 等稳定版本上。目前这个项目提供了 Device Management 的配置文件,通过这个配置文件,用户能够推迟 macOS 更新最长 90 天,具体效果是:

  1. 阻止「今晚安装」和「立即安装」的提示。
  2. 阻止系统设置中「有新版本」的数字提示。
  3. 检测并选择性阻止 macOS 系统应用的安装。

我的 Mac Mini 安装了 Tahoe,但我的主力机 MacBook 还是 Sequoia,我也不打算更新。我时常会收到系统更新提示的骚扰,这个项目帮助很大。顺带一提,我觉得这句话我永远也说不够:macOS Tahoe 毁了 Safari!

访问: travisvn/stop-tahoe-update

当下

平淡无奇的日常

本周是待在老家的最后一周,周末就回家了。回去之前除了每天给弟弟补习英语,偶尔出门闲逛,坐在及其不舒服的桌椅上看剧和玩网,以及读读书和写写代码之后,就没干别的了。

唯一的例外是周二出门和高中同学玩剧本杀,两三年没见面,感觉大家都没怎么变。不过,倒是有不少人惊讶我瘦了好多,还挺爽的。剧本是不用带脑子玩的类型,很俗套的家庭纠葛,结婚、争彩礼嫁妆、离婚、分财产和抚养权…… 不过倒是有很多吵架和演戏的情节,非常戏剧化,玩得还算开心。

我真的是个内向者吗?

在老家的几周,每天都想出门闲逛,但又找不到地方去。回家之后,倒是每天都想在家待着,要逼自己多出门走走,取个快递、倒倒垃圾之类的。在家多快乐,走出书房就可以去吧台给自己冲杯咖啡,冰箱里没有被喜好囤积的老人塞满不知道是什么的冻货,每个地方都是干净整洁的。

就决定是你了,口呆花!

Weepinbell 稳步开发中(指周日的时候突然想起来自己打算用 Clojure 写个 Webmention 接收端,这才 cd 进项目目录)。周中把 Webmention 规范 里有关接收端的部分仔细读了一遍,发现这真的是一项非常简单的技术规范,门槛并不高,只是知名度太少,导致普通用户没有开箱即用的选择。

简单到什么程度呢?大概就是发送端只需要向接收端发送一个 POST 请求(只包含 sourcetarget 两项数据,表单格式,不用 JSON),而接收端也只需要处理这一个 POST 请求,检查一下 URL 是否合法、有没有自己引用自己的情况、爬一下 source 看看是不是真的引用了 target。除了规范要求 Webmention 验证应该异步进行之外,就没有太多其他的技术规范了,收到 Webmention 之后要怎么存储、怎么展示、作何处理,都是接收端自己决定。

用 Clojure 编写 Web 应用的体验也很好,可以直接偷 Java 生态的库来用(比如,我验证 URL 的时候就用到了 apache.commons.validator,提取域名的时候用到了 java.net)。由于需要异步编程,还研究了一下 clojure.core.async 库,发现 Cloure 竟然支持和 Go 语言类似的并发模型,有 gochan,没想到偷完 Java 生态,还能偷 Go 的异步编程最佳实践来用,而且能复用编写 Java 和 Go 两门语言的程序的经验,真的很舒服了。

处理 Webmention 很显然需要一个消息队列:把所有待处理的 Webmention 都放在一个 channel 里(在 Go 语言里是c := make(chan type),在 Clojure 里是 (def c (chan))),然后启动一个或多个 goroutinechannel 里取出 Webmention 对象,爬取 source 验证是否包含引用,确认无误之后存入数据库,这些都可以轻松地异步执行。不过 Clojure 里应该是没有 goroutine 这个东西了,不知道底层是不是 Java 那臃肿的 Thread。无论如何,能够直接写 (go ...) 进行并发就已经很好了。

至于存储,我还在思考选用什么数据库。尽管在部署应用时常用 SQLite,但开发时我只用过 MySQL 和 MariaDB。我想,这正好是尝试新技术的机会,而且 Webmention 相互没有关联,数据结构并不复杂,兴许用 NoSQL(非关系型数据库)很合适,正好可以试试 MongoDB。另外的选择是用 SQLite 存储 JSON 数据,或者直接把所有 Webmention 都放在一个 JSON 文件里。这些都是下周要去做的事情了。

最后解释一下为什么项目名字叫 Weepinbell 吧。因为不想起名字,又受 Repokemon 启发,决定选一个宝可梦的名字。一开始想取 Web(网络/蜘蛛网)的意思,选个配色和 Clojure 的蓝绿色调相似的宝可梦,所以看上了滴蛛(Dewpider)。不过本人很讨厌蜘蛛,而且 mention 这个词也完全没体现出来。最后翻来翻去,选择了口呆花(Weepinbell)的名字。因为前两个字母 We 和 Webmention 的前两个字母相同,而后面的 bell 一词意为「铃铛」,可以表示「通知」,而 Webmention 本身的用途就是通知,通知作者他的内容被另一个站点上的内容引用了。

切片

  • “哈!你用浏览器编辑文本。” —— NeoVim 的主要贡献者 TJ DeVries 在 2024 年 VimConf 劝告 (Neo)Vim 用户们不要用这种话说服别人使用 (Neo)Vim。

    可是,VS Code(以及 Cursor 等 VS Code 分支)就是浏览器啊!

    逃离现场。

  • 看到日本网站丑丑的设计反而觉得有点喜欢,大概是因为喜欢多样性,扁平、单色、冷静、克制的设计看太多了,不免有些乏味。( 相关链接 )最近在 IndieWeb 上闲逛的时候,也看到了一些不太主流的设计,我想这是个性的体现,比在主题商店找到的好看模板更吸引人。

  • 想把旧电脑的硬盘拆下来做成移动硬盘,硬盘盒已经买好了,结果我拆电脑的时候被父亲撞见。

    他:电脑留给我用,硬盘我给你买一个。

    我:啊?现在硬盘贵得很……

    他:没事,要好多钱你给我说嘛。

    于是我现在有了一个 2TB 大小的移动 SSD,目前用来备份 iCloud、S3 储存桶和服务器,兴许还会存点音乐和剧什么的吧。感觉可以做一个末日2生存包,存一些音乐和《老友记》全集,应该能维持很长一段时间的 san 值健康。

  • 又买了管道疏通剂,尝试疏通浴室的地漏。用完一整瓶疏通剂之后才发现,水排得慢并不是因为管道堵塞,而是滤网的设计缺陷。说是设计缺陷毫不夸张,因为那个金属滤网上有一个类似盖子的结构,会在安装上之后挡住排水口,只留下非常小的缝隙;而盖子旁边是环形的凹槽,那里会积水,大概是和管道形成了类似连通器的结构,凹槽水满了之后会从盖子的缝隙流到管道里。

    这貌似是给水量不大但有排水需求的场所使用的滤网,能够有效拦截固体避免堵塞,但根本没办法在淋浴时有效排水,房东装这房子的时候是怎么想的?

    室友:能不能把滤网翻过来用?

    如果忽略掉那个朝上的盖子,洗澡时小心不要踩在上面的话,排水就很顺畅了…… 忍了半年的积水问题,竟然是这个原因吗……


  1. 用词 页面已更新。 ↩︎

  2. 指断网。 ↩︎

稻草人周刊 Vol.69

如果第 69 期周刊都没有双关的话,那就是不尊重数字了。

No shit. Math class. Never was good

真的,数学课,从来没学好过。

连接

词典有什么用?

📻

很惊喜,写完《 论遣词造句 》这篇文章的三天后,我就听到了树老师的这期播客,讨论纸质词典的发展历史和现状,也谈到了语言的主观和规范等话题。

简单来说,词典在一开始是知识分子建立共识的工具,并非是像如今的《新华字典》一样人尽皆知的东西,如今人们认知中的词典其实是相当现代的产物。美国的韦氏词典,作为一本现代意义上的词典,实际上承担了相当大的政治作用,编撰者 Webster 本来想把它取名叫「美国语言词典」,因为当时美国正在从英国独立出来,所以他野心勃勃地想要创造出独立于 English language 的 American language,在文化上与英国做出区分。在中国,词典对用词乃至意识形态的规范,也是相当政治化的,比如「封建」一词就从对政体的中性描述,变成了贬义词,与「落后」关联起来,如今人们能轻松地说出「封建落后」这个词——用播客中的话来说:这是马克思主义对中文的强奸。还有「爹味」一词,也是互联网上的女性主义者对「爹」的贬义化,女人用这个词批评男人,男人用这个词自省,人们也用这个词评价女性。

不过,近年来,在词典行业内部已经建立起了这样的共识:词典不再主动规范语言,而是描述语言的变化。英语中 Literally(字面意思上地)这个词被滥用,以至于意思变得完全相反,人们可以自然地说出「I would literally die if I do that」(那么做的话,我字面意思上地就死了)这种话,这成了语气词,用来表示夸张。这显然是错误的用法,但词典不再揪着错误不放,而是把错误归入词典的一部分,描述这种变化:这个词也有表示夸张的意思,一些人会对这种用法感到不舒服,但就是有人会这么用。

播客最后讲到,语言本身就无法做到绝对的客观公正,事实上一些力求客观公正的人,也是用着主观的标准来判断是否客观公正的。过去人们尝试过规范语言,但无法做到。如今人们面临的困境,比如互联网俚语对词汇的污染,实际上和以前没有什么不同,以往任何一个时代的词典编撰者,都会说「这是语言最混乱的时代」,各种现象给语言带来了大量的新词汇,而互联网只是其中之一。即便互联网的信息传播速度再快,人类的脑容量也是一如既往地小。

无论语言怎么主观、怎么混乱,都是一个「凑合着用」的东西,只不过「凑合着用」的标准在不同的人眼里也是不同的,语言的使用也有高低之分。

顺带一提,我在这周发布了 用词表 页面,阐述了我的用语习惯和原则,意在自我规范。如果你感兴趣可以读读,也可以考虑给自己的博客加上 /glossary 页面。

Token 焦虑和老虎机

📜

许多美国科技公司开始学习中国的 996 工作制度,作者担忧雇主对 Agent 编程的鼓励(甚至强求)会让不道德的工作制度更容易实施,毕竟,如果你做的只是告诉电脑应该怎么做、审查它的代码、每天用十几个小时「带娃」,你真的是在工作吗?

也有不少人意识到,使用 LLM 编程就像是玩老虎机,让人以为只要再写一句提示词、再拉一下拉杆、再审查一遍代码、再听一句「You’re Absolutely Right!」,就能得到梦寐以求的产品。实际上这不会发生,但如果呢? 有不少重度 Agent 编程使用者,发觉自己有成瘾倾向。作者指出,新型的瘾症往往需要一段时间以后才会被当作需要治疗的症状。对 LLM 上瘾完全有可能是下一个被发现的新瘾症。1

动脑筋想一想:在工作场所推行(甚至强制使用)具有成瘾性的技术,实际上就是在让员工对工作上瘾。这不是很可怕吗?这真的道德吗?这会成为常态吗?情况会不会变得越来越糟糕?尽管我还没有开始工作,但我有在 V2EX 等中文程序员社区发现有公司开始给员工购买 AI 编程工具,这种风气似乎也会席卷国内?

容许我跑个题,如果读者有使用 LLM 的不良习惯,并且已经意识到了一些问题,我有或许值得一试的方法:选择一门小众到互联网上的公开信息少之又少的领域,让 LLM 没办法帮你。至少,我在折腾 Akkoma 的时候,LLM 只会自信地给我生成一大堆根本用不了的命令;我在自定义 Forgejo 的界面时,LLM 一直误导我,使我走了许多弯路、几次放弃,最后发现有一篇官方文档已经给出了详尽的指导——语料缺失了,幻觉就愈加明显。此外,我写 Clojure 代码觉得有新鲜感和动力的很大一部分原因是,我知道 LLM 几乎帮不了我,而且,这门语言本身就足够有趣,我为什么要让 LLM 剥夺我的智识享受?

想象刷视频和阅读的区别,两者都能带来满足,性质却是完全不同的。永远都要选择后者

高强度脑力活动对体能锻炼的影响

📜

大脑每天消耗总热量的 20%,是最耗能的器官,但高强度的脑力活动并不会让大脑消耗更多的能量。这 20% 的热量主要用来维持神经元活跃,什么也不想和拼命思考,每分钟消耗的能量不会有实质性的差别。

然而,大量的脑力活动却对锻炼有影响,可能降低运动表现。

简单来说,脑力劳动会增加腺苷的积累。根据我从《 绝佳时间 》这本书里了解到的为数不多的生理知识,腺苷是「疲劳信号」,而咖啡因会阻碍腺苷与受体结合,这就使得咖啡具有提神作用,腺苷受体被阻碍过后,大脑就感觉不到疲惫了。高强度脑力活动会加快腺苷的积累,让人感到疲劳,如果在腺苷积累后锻炼,大脑对疲劳的判断就会提前,导致身体没累,但大脑觉得它累了,无法坚持下去。

总之,避免在长时间工作后进行剧烈运动。我的建议是把运动放在早上,那个时候腺苷的数量最少,而且运动还会使得身体释放其他激素,对专注有益。这篇文章的作者建议,每周安排两次高强度锻炼,在锻炼当天避免长时间工作,或者间歇性休息、放松、进行需要大脑参与更少的活动。其他日子也可以进行较低强度的运动,影响不大。

当「当预言失灵」失灵

📜

在《 如何在黑暗的房间里找到一只黑猫 》里读过一段故事,我在之前的文章中也引用过:

这样被认知裹挟的例子,可以引入美国社会心理学家利昂·费斯廷格的认知失调理论来解释。这位心理学家和同事发表于上世纪五十年代的著作《当预言失灵》中讲了这样一个故事:一个小型的宗教相信世界会在 1954 年 12 月 21 日毁灭,只有信徒才会被外星人救走,当「世界末日」到来时,所有信徒都在屋子里祈祷,可十二点之后,什么都没有发生。在数十分钟的安静之后,这些信徒分别作出了以下解释来合理化自己的认知:

  1. “或许是房间里的钟错了,我们应该再等等。”
  2. 确认钟没有问题之后,有人说:“或许是外星人使用了不同的时区,我们应该再等等。”
  3. 外星人直到早上也没有来,于是宗教领袖决定到房间外接受外星人的启示,之后她们告诉信徒:“因为你们的虔诚,人类被宽恕了,地球不会毁灭。”

——《 挑食如何帮我发现自己的认知边界?

一篇 新的研究报告 表明,案例中的宗教团体,有近半数都是卧底的研究人员,其中一个成为了他们的领袖,引导他们说出一些写在书里会有看点的话。当预言失灵时,其实有一部分成员收回了之前的言论,或者直接离开了。

这么看来,《当预言失灵》的罪行简直跟《 天才在左,疯子在右 》一样恶劣。后者是伪装成「真实精神病人访谈手记」的网络小说,不仅欺骗读者,还污名化精神病人;前者明明是正经的社会心理学著作,可竟然误导大众,在研究层面造假。书可以烂但不能骗人。

我不喜欢魔法

📜

作者表达了他对软件开发中的「抽象层」的厌恶,尤其是前端开发中的 React 和充满了魔法的 LLM。作者承认他的态度不够务实也不够「商业」,对那些想找工作的开发者没什么价值,他的态度更像是「控制狂」——必须理解程序调用的每一行代码,盲目相信第三方库和第三方框架让他感到不舒服。也因此,他讨厌 NPM,因为通过 NPM 安装一个 JavaScript 库,这个库会转而安装更多的 JavaScript。

这不怪他,要怪就怪 JavaScript 生态,依赖地狱已经是常态,就算换用 PNPM 和 Bun 这些更现代的工具也无法解决。我已经不知道有多少个人吐槽过前端开发的体验极差,有大部分工作都是在维护和更新依赖。

一只戴着眼镜的蓝色地鼠突然拖着小黑板出现,指着一行粉笔字念到:

A little copying is better than a little dependency.2

来点依赖不如复制粘贴。 ☝️🤓

可惜几乎所有前端开发者都习惯了引入一大堆依赖库,这大概也是为什么 NPM 软件包这么容易被投毒吧…… 谁来救救我们前端开发者……

至于 LLM,这种软件本身就是个巨大、复杂、计算昂贵的东西,用它来写代码尽管不需要维护很多依赖项,但也相当于是把自己没有理解的、别人写的代码放进代码库里,作者把它比作「涡轮加速且有更多抽象层的 NPM」。

过度依赖第三方库和框架,和过度依赖 LLM 编程,都会让代码变得难以维护。作者认为他对抽象层的厌恶来源于他对项目的忠实,他做的很多都是计划运行十多年、几十年的长期项目,因此,他更喜欢让自己更接近 HTML、CSS 和 JavaScript,扔掉 React 做的那层不必要的抽象,这使得长期而言,代码变得更容易维护。

扔掉了魔法,虽然开发速度慢,但开发体验令人愉悦——没有依赖地狱,也没有别人写的、自己不理解的代码,这种让人坐立难安的东西。

嗯,总而言之,远离 React——真可谓是前端界的 Java。

星群

AllLookSame?

各种测试题,给难以分辨区别的人事物归类,其中一套题是在纽约街头拍到的 18 张中日韩人的照片,测试题的内容是分辨某张照片的人是中国人、日本人还是韩国人。

我答对了…… 8 题…… 平均成绩是 7……

中日韩人真的有明显的外貌区别吗?

此外,这个网站居然还是用 WordPress 做的,所以每道题之间加载时间太长我也没感到意外。WordPress 比起博客软件,说是通用型的建站软件还差不多,其功能何止是臃肿。

访问: AllLookSame

Hacker News 的 macOS 客户端

Hacker News 设计的 macOS 原生客户端,用 SwiftUI 编写。这下在 macOS 上摸鱼变得更容易啦!

引用 Hacker News 上的一条回复:

No No. Don’t do that, don’t make it better and easy to use. I’m already addicted and spent more time than I should. Now, this app that I can keep it open all day!

不不不,别这么做,别做得更好更易用了。我本来就上瘾了,花了不该花的时间。现在这个 App 我能一整天打开看!

访问: IronsideXXVI/Hacker-News

modern.css

列举了一些老旧的前端开发模式,并给出了现代的 CSS 替代方案。比如弹出窗口就完全不需要用到 JavaScript,使用浏览器的 Popover API 就可以,可以只用 HTML 和 CSS 实现。本站也利用这个 API 移除了部分 JavaScript 代码。

访问: modern.css

当下

装修桉树

除夕夜当然没看春晚,而是在给 Eucalyptus (我的联邦宇宙服务器)安装新的前端。由于我使用 Akkoma (Pleroma 的分支),而我很喜欢的 Phanpy 是为 Mastodon 设计的前端,Akkoma 自带的 Pleroma-fe 虽然不丑,但并不好用。于是,我安装了 Nicolium ,这个前端的设计更接近 Mastodon(以及 Twitter),对 Akkoma/Pleroma 的兼容性很好。

不过,Nicolium 也有我不太喜欢的地方,比如依赖 CSS-in-JS(一种在 JavaScript 里为元素编写样式的技术),还是用 React 编写的,所以性能…… 只能将就。偷偷把「写一个兼容 Akkoma 的前端」加入愿望清单。

尽管装新前端主要是为了优化自己的网上冲浪体验,但如果读者需要到文章对应的帖子底下评论的话,有一部分人可能会直接访问 Eucalyptus,如果有更友好、更现代的前端,对访客而言也是好的。

博客的调整

如果你翻到最底下,会发现文章的互动区有了一些改动:

首先,点击 + 按钮,互动浮窗会在网页正中间打开,这是通过 CSS 的 popover API3 实现的,我把相关的 JavaScript 移除了。这个 API 很好用,要实现弹出窗口只需要:

<button popovertarget="mypopover">Toggle the popover</button>
<div id="mypopover" popover>Popover content</div>

我想起还有同样好用的 <details> 标签,也能不借助 JavaScript 实现交互效果。点击互动区的一行字会展开 Webmention 回应(如果有的话),这个之前也是用 JavaScript 实现的,完全可以使用纯 HTML 的方案。

我还顺便优化了 Webmention 的样式,现在应该会看起来更舒服一些。

另外,最近总是在博客谈起 Webmention,但这项技术的普及率还是太小了,有许多人都不会用,中文资料少得可怜。我想我可以写一篇相关的文章,做点贡献。不过这意味着我要再深入了解一下这个规范,读读 W3C 的原文。

要对一门技术熟悉起来,最好的方式当然是…… 实现它!所以,我创建了 Weepinbell ,准备用 Clojure 写一个 Webmention 接收端。不过目前还处在新建文件夹的阶段。4

We code and we fight.

自定义了我的 Forgejo 实例的外观,把主题色改成了「鼠尾草色」,图标改成了「三头龙」。首页的模板也改了,现在访问 首页 只会看到图标和站点名字,干净不少。

技术细节请移步 罐子里的相关笔记

其实刚装上 Forgejo 的时候我就动了自定义的心思。根据 官方的说法 ,修改前端界面的做法其实是「不被支持」的,而 Forgejo 本身比较小众,教程少之又少。当时的我心术不正,求助于愚蠢又自信的 ChatGPT,还在 DeepSeek 和 Kimi 之间辗转,没有一个帮我解决了问题,都非常自信地给我生成了一大堆根本用不了的解决方案。

这周又动了心思,重蹈覆辙,沮丧之际发现这篇 官方文档 提供了相当详细的指导,耐下性子读完过后就…… 非常顺利地实现了需求。

教训:不要吃 LLM 反哺的垃圾,

对了,我还没有在博客上解释过我的 Forgejo 实例为什么叫 Hydra。主要有两个原因:

  1. 之前读过一篇文章,把创建个人项目,实现想法,比作「与恶龙战斗」。依稀记得原文写的是「Fight the Project Hydra」。忘记标题和来源了,但内容一直记得。
  2. SVG Repo 上找到一个三头龙的图标,乍一看真的很像 Git 分支。

谈话间,有人又重写了个人主页……

上一版个人主页存活时间可能还不到一周吧!不过技术选择倒是没改,还是 Clojure。改来改去的主要原因是对结果一直不满意,现在感觉还不错,首页大概是不会改了,其他页面可能会调整一些细节。可以访问 eltr.ac 看看效果,欢迎来玩。

设计新主页的时候还找了很多参考,当时在联邦宇宙上发了个 讨论串 收集素材,顺带提及那些我喜欢的创作者,送去喜爱,没想到收到了一些 Fedi 友的推荐。这里列出一些我比较喜欢的链接:

  • anhvn :关注了 anh 的 Mastodon 账号 ,某天发现她发了一条帖文,内容是「every other day im like i gotta redesign my website…………」5。感同身受呢。
  • wukko :我在使用的 Helium 浏览器背后的开发者,他的个人主页简洁得十分优雅。头像是《宝可梦》里的喵喵,点击头像会下喵喵雨,天哪……
  • meyerweb :很喜欢背景的质感和插图。
  • caffeine.computer :想在我主页的某个角落放一个写着「千万别点!」的按钮,按下去之后我的头像就会变成一个有克苏鲁风格或者怪核风格的眼睛,背景会变成黑色,文字描述也会变得诡异……

切片

  • 长辈对电子设备没有距离感,觉得屏幕是可以随便看的东西,尤其是电脑这么大的屏幕。还好,我浏览的页面有相当大一部分都是英文的,只会给他们留下「我在好好学习」的印象,这就是学外语带来的便利吧。

  • 我究竟是买块大点的硬盘呢,还是再攒攒买台 Steam Deck 呢,还是买台 Steam Deck 呢,还是买台 Steam……

    不过话说回来,要逐步脱离苹果生态和 iCloud 的话,我的确需要一块硬盘用来存个人数据,以及做本地备份,可现在这个行情买硬盘属实是太不赶巧了。

    Deck 呢,还是买台 Steam Deck 呢,还是……

  • 在看《蛇蝎女佣》,目前看到第三季,主创也创作了《绝望的主妇》这部经典美剧。嗯,很好看的狗血剧情。 没别的,纯粹消遣。


  1. 顺带一提,欧盟似乎已经对 TikTok 采取措施,认为短视频的推荐算法和无限滚动模式是具有成瘾性的。如果 TikTok 不整改,就会被罚款。参见: Solidot  ↩︎

  2. 这句话来自 Go 语言创始者之一 Rob Pike,参见 这个 YouTube 视频 。 ↩︎

  3. 有关这个特性的资料,可以查阅 MDN 。 ↩︎

  4. 名字想好了,连图标都找到了,明明是很大的进展! ↩︎

  5. 译文:“每隔一两天我就这样:我必须重新设计我的网站……” ↩︎

迷失于图形界面

学校开设了 Python 课程,课程还涉及人工智能相关的内容,但也有相当一部分内容是 Python 程序设计基础。自然地,第一堂课的内容是配置开发环境,自然地,配置开发环境的内容就是安装 PyCharm,并在 PyCharm 的图形界面里找到对应的面板安装要用的依赖项。

一般来说,只要老师没有妨碍我愉快地用我爱用的编辑器(Neovim)写代码,我是不会说什么的。只不过,这位老师之前也教过我数据库的课程,他对于开发工具的态度在我看来非常典型,所以值得一谈。

不解之词

老师在演示如何用 PyCharm 安装依赖时说了这样一句话:

“我看有的人用写代码的方式就能把依赖安装上了,那样好像是会快很多,有些人就是能找到捷径啊!”

尽管我对 Python 生态不熟悉,但根据他的描述,我大概明白他说的是类似 Node.js 的 package.json、Go 语言的 go.mod 和 Maven 的 pom.xml 之类的东西。在项目根目录的一个文件声明项目所需的依赖之后,执行安装命令,就能在当前项目下安装所需的依赖。这实际上是相当常见的实践,有正经工程应用的编程语言都有类似的东西。

在讲授数据库原理及其应用这门课的时候,他要求我们安装的是 Navicat ,一个管理数据库的图形界面工具。我不想用闭源的商业软件(而且我当时的操作系统是 Arch Linux,似乎也没有在 AUR 上找到包),所以选择了 DBeaver 。我记得很清楚,我除了在需要提交作业截图时使用了这个软件,其他时候都是用 MariaDB 自带的命令行工具,手打 SELECTINSERT INTO 等语句,因为我真的不想在层层叠叠的图形界面里找我想要的功能。

我记得有一次交作业我实在不想打开 DBeaver,于是提交了终端截图,结果下一次上课的时候就听到他这样说:

“有的同学直接输入 SQL 语句,都不嫌麻烦的吗?临时输入一两句还好,要输的东西多的时候,就直接在软件的表格里编辑数据表就好了啊。”

那这和用 Excel 有什么区别!

到目前为止,这还只是操作习惯的差异,不足为奇。所以,老师是一个喜欢操作图形界面的人,这不代表他是个差劲的程序员,程序员的能力不体现在工具的选择上,不熟悉命令行工具又怎么了?用 Neovim 和 Emacs 就比用 VS Code 更高尚?用 Postman 就比用 curl 更愚蠢?用集成开发环境也不代表无能啊。

“大家用 pip 安装依赖的时候注意一下啊。”老师好像是突然想起了以往的经历,在讲课时突然插入了这样一句话,“用 pip 安装的第三方库和你的 PyCharm 里的第三方库可能不会互通,就是说你用 pip 安装了第三方库之后,在 PyCharm 里可能用不了,要在 PyCharm 的图形界面里安装依赖。”

我没学过 Python,但确实用 Python 写过不少脚本来帮我自动化处理某些操作,比如批量修改博客的 Markdown 文件格式、替换文本之类的,我也的确遇到过没办法正常加载依赖的问题。当时我只能改变实现方式,避免调用第三方库,一直没明白原因。这么说,我的问题就要从老师那里得到解答了?

没有,他直接往后讲了,什么也没说。他自己大概也不明白为什么 pip 安装的依赖会没办法在 PyCharm 里使用。

求助熟练操作蟒蛇狐狸 之后得知,这是 Python 的 虚拟环境 导致的,即 venv。虚拟环境会将软件包与全局环境的软件包隔离开来,只有在环境内显式声明的软件包才可用。pip 默认把软件包安装到全局环境中,而 PyCharm 会帮忙管理虚拟环境,两者不在同一个环境里操作软件包,所以没办法直接互通。

这就解释清楚了,所以我只需要执行 source 命令进入虚拟环境,然后在虚拟环境里管理依赖和运行 Python 程序就可以了;如果安装了 uv,使用 uv run ,可以直接在项目的环境里执行命令。1

不过,老师看起来教授 Python 也有几年了,为什么会不清楚这个基础概念呢?难道是我误解了老师的……

好了,是时候放下我对教师的假惺惺的尊敬了。

图形界面的魔法

图形界面的优点在于,它屏蔽了很多细节,避免直接和复杂的配置文件和基础工具打交道。这无可厚非,软件设计的一大原则就是「信息屏蔽」,让用户关注更重要的事情。可是,对于程序员来说,这些细节真的应该被屏蔽吗?一个好的程序员不应该了解自己所使用的开发工具是如何运作的吗?

我在英文博客上写过一篇《 Java Development with True IDEA 》,强烈抨击了 IntelliJ IDEA 单边主义,2并把软件开发所需要的 IDEA 重新定义为 Instant(快速)、Deliberate(审慎)、Elegant(优雅)和 Attentive(专心)。

我当时连续使用 IDEA 将近一年的时间,原因在于:没了 IDEA 我就不知道怎么开发 Java 项目了。之所以会这样,是因为 IDEA 给我屏蔽的信息太多了。不操心底层真正发生了什么的后果是,我根本不知道底下发生了什么。当我按下 IDEA 的「运行」按钮时,究竟有什么命令被执行了?我不清楚,以前的我也不关心,我只知道「这个按钮能让我的代码跑起来」,就像魔法一样。

可是,要是有一天魔法失效了呢?当我按下「运行」的时候程序没有被执行,当我按下「同步」按钮的时候依赖没有被同步(IDEA 的设计非常奇怪,有时候「同步」按钮根本不会显示,我必须在一个下拉框里找到某个菜单项才能正常同步依赖),当我的程序没有被正常编译,而我在密密麻麻的界面里找不到相关的配置项时,我要怎么办?

要找到图形界面里的某项配置可真不简单。

首先,我很难用语言描述清楚我要找的是什么,如果描述不清楚,又怎么在搜索引擎里搜索教程呢?其次,就算找到了我要的东西,有人告诉我这个东西要在 Project Strucutre -> Libraries -> More 里面找到,我也要在硕大的图形界面里搜寻这些文字的位置。再次,就算有截图指引,我也有可能因为版本差异而没有办法在图中所示的地方找到我需要的东西。

有人可能会因为熟悉图形界面迷宫而感到自豪吧。我记得我在各种按钮、菜单、面板和输入框之间穿梭,只为了调整项目的编译方式时,有一个不熟悉计算机的朋友突然凑过来看我在做什么,发出了「好厉害」的感叹。可是,究竟为什么要学习一套可有可无的、建立在基础工具之上的抽象,而不去直接使用基础工具呢?

这就好比用 React 开发一个只有一页的网站,而这一页的内容只是几句话和几个链接——那你为什么不能直接写 HTML,而要去操作虚拟 DOM 呢?这层多余的抽象究竟给你带来了什么价值?

我为什么要学习 Postman 的图形界面,等待它花几秒钟的时间启动一个 Chromium 实例渲染一个网页,学习和记忆 URL 输入框 和 HTTP 请求方法的选择框的位置,只为了发一个简单的 HTTP 请求?我为什么不能直接使用 curl?如果我只会用 Postman,我就不知道要怎么在其他的地方发送 HTTP 请求了,而 curl 却被安装在几乎任何一台计算机上,是很多软件的基础工具,无论是日常测试、运维还是开发工作,都能用到。我调试自己写的 API 会用 curl,我测试部署的服务有没有真的跑起来会 curl localhost:<port>,像 Hurl 这类与 HTTP 请求相关的软件也是在 curl 的基础上开发的。

显然,无论选用抽象层次很高的图形界面软件,还是最基础的命令行工具,都有学习的成本。那为什么要学习一套将你与底层隔离开来的抽象,而不是直接学习更接近底层的工具呢?

我承认抽象有存在的价值,但我反对过度且不必要的抽象。

专业与门槛

可能有些幼稚,但我又要举一个大学老师的例子了。不过这个老师本身就很讨人厌,说话爹味很重而且粗俗,还觉得自己和蔼可亲,他项目组里的学生能跑的都跑了。他身上有一个很多爹味浓重的人都有的典型特质:热衷于做「守门人」,强调门槛与专业性,踩在门槛上拉开自己与他人的距离。

他也喜欢使用图形界面,但原因,在我看来,并非是权衡利弊之后的选择,而是对门槛的维护。在我看来,如果你不想接触基础工具,只想要优化开发体验,那么选择简洁直观的图形界面工具也无可厚非,只要这是你自己选的。

设计软件架构常用 UML,即统一建模语言,UML 有各种不同类型的图表,用来表达架构、活动、操作的时间顺序、涉及的模块和对象等等,总之是便于沟通的标准化工具。既然目的是「沟通」,那么只要能准确表达,能让他人理解,就达到了目的。简单来说,只要图画得清晰,没有错误和歧义,能够高效沟通,就是好图。

但是这位老师显然不这么认为。

“有的同学用 Visio 画图,这样不好,我们作为软件工程的学生,要使用专业的 UML 绘图工具。你作为专业的软件工程学生,连专业的画图工具都不会用,怎么行!?”,老师神情严肃地讲道,“我在群里发了两个软件,第一个软件我们把他叫作 EA3,这个软件是商用的,你也可以用第二个开源的 StarUML。4

Visio(以及开源的 draw.io)不被他视作专业的 UML 图绘制工具,并不是说架构师没办法用它们画好图,而是因为它们缺乏与 UML 相关的抽象。这位老师强调,Visio 是矢量图绘制工具,而不是专业的 UML 图绘制工具。这两类工具的区别就在于抽象层次的高低。

之所以这么说,是因为,UML 图明显就是图片的一种,一般也是作为矢量图来绘制的。能绘制矢量图的工具当然也能绘制 UML 图,说白了,UML 图里最常见的元素就是方框、圆圈、直线、箭头、小人和文字,连 PowerPoint 都能画这种图。只要使用了正确的建模语言和规范,保证图片清晰易懂,就是好的 UML 图。

前文提及的 EA 和 StarUML 等软件,当然也是能画方框、圆圈和小人的,只不过它们只能用这些元素来画 UML 图。使用这种工具绘制 UML 图是自然的,哪怕对建模语言本身不熟悉的人,也不容易画出错误的图。

通俗地来讲,这两类软件的区别,就是化学原料和包装好的清洁剂的区别。这位老师觉得:使用一水柠檬酸溶液来清除水垢是不专业的,应该使用包装上写明了「水垢清洁剂」的清洁产品,才显得专业

破除魔法

让我总结一下目前为止我的观点。

长期依赖于高度抽象的图形界面工具,尤其是在一开始就没有了解过低层次抽象的前提下,会让人忽略最基础的知识。这是个人层面的问题。社会层面上,会创造出本不应该存在的门槛和鄙视链,仿佛使用高度抽象的软件系统就更专业。

这种心态不罕见,我相信:如果让所有的 Java 开发者停止使用 IDEA,有相当一部分人会不知道如何启动 Spring Boot 项目(答案:用 mvn spring-boot:run);如果你告诉别人你用 GIMP 编辑图片而不是 PhotoShop,有相当一部分人会认为你不够专业。

这么说来,因为普遍认为前端技术很简单,所以常常被鄙视的前端开发者,实际上大多都脱离了这种窘境,因为前端开发的必要工具之一就是 npm 或者其他相关的命令行工具,我很少看到有人用 JetBrains 的 WebStorm,通过操作图形界面管理依赖项。当然,前端开发也有自己的问题。

使用 LLM 开发也是,许多人宁愿用高度抽象的自然语言描述需求,也不愿意手写代码,就算在遇到 Bug 时跟 Agent 发疯也不愿意停下。5如果他们愿意去看看真实的代码,接触被抽象掩盖的东西,他们就不会如此狼狈。我想这背后也是相似的心态在作祟,而且「程序员应该跟上潮流用 LLM 写代码,手写代码是落后的」这种思想,似乎也有愈演愈烈的苗头。这种潮流,何尝不是痴迷于高度抽象的软件,所造就的门槛?

最后,我想说的是,不要怕麻烦,接触低层次的抽象并不可怕,反而能帮助自己建立起对软件的清晰认知,而清晰是非常宝贵的。就像学习 C 语言有助于程序员理解内存、指针和数据结构等基础概念,就算不用 C 做开发,有了这些理解,也更容易写出高性能、速度快的软件。

从长期来看,对软件的清晰认知,要胜过生产力和专业的外表,而扒开抽象的外壳向内看,是培养这种认知的关键步骤。


  1. 参见: Running commands in projects | uv  ↩︎

  2. IntelliJ IDEA 是 JetBrains 开发的,专注于 Java 和 Kotlin 开发的集成开发环境。一般来说,学校里教 Java,要么会要求学生安装 Eclipse,要么就是 IDEA。IDEA 是最常见的,人们几乎不会思考开发 Java 软件的其他方式。 ↩︎

  3. 全称是 Enterprise Architect,中文意思是「企业架构师」。英文里的 Enterprise 除了指代企业和创业,也和企业家精神和专业性有关联,所以也可以理解为「专业架构师」。 ↩︎

  4. 我了解之后发现,StarUML 也是专卖软件(Proprietary software),最初以 GNU GPL 协议发布了开源版本,但开源版本在 2010 年就停止维护了。当然,就算它是自由软件,我也不想用,原因在于它是 GUI 软件,很重,另一个很关键的的原因是,它是用 Electron 和 Java 写的。 ↩︎

  5. 顺带一提,我甚至见过有 Java 开发者非常认真地讨论,要不要双开 Cursor 和 IDEA 做开发,因为他们觉得需要用 AI 编程,而离开了 IDEA 做 Java 开发又很麻烦。 ↩︎

理想的日常

这是我的「 BlogBlog 同乐会 - 2026 年 3 月 」的投稿文章。本月主题是「 理想的日常 」,由 Alex Hsu 主持。如果你有自己的博客,欢迎一起来参加!


重庆已经到了不需要穿厚外套出门的时候了,总觉得今年的春天来得比以往早。我昨晚三点以后才睡着,今早八点就被阳光叫醒,油腻和不适的感觉裹缠着我的身体。从自己租的房子回到老家之后,生活秩序被打乱,也没有躺在熟悉的床上,总是不能安稳睡去。我记得一个月前收拾行李的时候,恨不得把整个家都搬回去,担心离开之后,住处没有好用的清洁剂、没有好写的笔,担心家里的盆栽会枯萎。

寒暑假我都会找点事情做,以便留在学校,因为生活方式的转变是痛苦的,一周还好,如果是一个月,我甚至会说是不人道的。一两个月的时间不长也不短,不够我建立起新的生活秩序(比如,不值得我为此把老家里所有我看不惯的堆满杂物的角落收拾干净),却又超出了我对生活失序的忍受范围。此外,我极度厌恶被他人审视的生活,我还不需要一个做不到忌嘴的糖尿病患者每天都提醒我不要喝冷水——实际上,除非是锻炼后立刻喝冰水,冷水并不会影响健康,喝太热的水反而会损伤食道黏膜。

说实话,我觉得固执的老人更像大语言模型,他们局限的生活经验就是语料库,未受教育且倔强难改的思维方式就是模型算法,而他们输出的内容,就算毫无道理,语气也带着他们本不该有的自信。要是我以后变成了一个只说不会做,因为自己生活空虚所以只会窥探别人的生活并且指指点点的老头儿,我希望有人能就地处决我,我该死。处决的光荣执行者,将会是为全人类做出贡献,让世界变得更美好的英雄。

好了,牢骚发完了,不依不孝的话也说了。现在,还留在这里的读者们,请允许我为你讲述我理想中的日常。


曾经和现实中认识的人聊天,谈到过「理想的一天是如何度过的?」这个问题,我忘记当时的回答了,唯一还能回忆起的细节是起床的时间。我说,我会在早上八点半起床,当时有人问我为什么不是十点,或者十二点。

我说,早晨很安静。

记不清从何时起,我不再喜欢睡懒觉,折磨我的生物钟并不令人愉悦。换成现在的我,大概会选择早上七点起床,甚至更早。晚起意味着白天的时间被缩短了,而我并不喜欢晚上我熬夜时的样子。据我所知,那个时候的我根本不会按照计划行事,状态也很差1,除非是为了自己有热情的项目赶工,而我们都知道,程序员是不该在晚上把代码提交之后就回去睡大觉的(这句话是 Paul Graham 说的)。考虑自己的健康和项目的安全,在意志力最薄弱的深夜抵抗继续编码的诱惑,就尤为重要——就算大半夜做完了,也不该提交工作,那还不如第二天早点起来做呢。

因为这一两年几乎没有断掉写日记的习惯,有记录自己身体和头脑的感受,也就逐渐在记录中发现,睡眠真的是生活质量的基石。一旦睡不好,我就容易暴饮暴食,运动表现也会明显变差,读书、写作和写代码虽然能够照常继续,但注意力很容易被其他信息夺走。我想,这是因为睡眠影响了认知活动吧。我相信良好的生活应该由七部分组成。

我的良好生活金字塔,记录在我随身的 M5 活页本里

良好的睡眠、良好的饮食、规律的运动、大量和广泛的阅读、创造力、安心的关系和平和的心。这七个组成部分自底向上支撑着彼此,在我看来,要是没睡好,就会忍不住食欲、容易感到疲劳,上面的六项也都会垮台。过往的减肥经历告诉我,对健康的体魄而言,吃比动更重要,皮肤问题和情绪问题甚至也可以通过好好吃饭来解决,只不过现代人很少有能够好好吃饭的。规律的运动,指的是提升心肺能力的有氧运动、提升肌肉力量的抗阻力训练,以及提升柔韧性的静态和动态拉伸——只跑步或者只去健身房撸铁,是臃肿且不平衡的,尤其是不应该忽略拉伸,柔韧性是身体最好的盔甲。

身体之上,才是头脑。这点我和 塞涅卡 的观点完全相反,我和他另一个相悖的观点是,他认为阅读应该忠诚于一个作者,而不是走马观花地什么都读,可我认为阅读应该广泛,尽可能了解不同的人对不同事物的不同看法,尤其是那些与我观点不合的人。不过,在我眼中,高质量的阅读应该是基于长文本的,文章或是书籍,短文本和微博客只起到记录、分享和社交的用途。阅读(还要加上「体验」)是对创作者的滋养,是灵感来源,所以创造力要置于其上。对我而言,写作和创造软件,都是创造力发挥作用的领域。

头脑之上,又是心灵。上面的图片展示的是我随身携带的「良好生活金字塔」,我还在书房的墙上贴了一个更详细的版本,金字塔的每一层都有更详细的划分,不过,「安心的关系」和「平和的心」这两层是空白的,因为我从未体验过这两者中的任何一个,它们是我无法想象的世界。

之所以在开始描写我理想中的日常之前,扯了一大堆没人爱听的理论,是因为我觉得有必要让读者知道我对良好生活的标准是怎样的,目的是建立起共识,以免后文显得突兀。我要是让读者毫无准备地了解到我每天都会把自己的身体掰来掰去,把脚放到头后面去,我认为是会令人感到措手不及的。


回到我的想象。现在是早上七点,日光透过窗户打在我的脸上,不早不晚,正好我把从一个睡眠周期刚结束时叫醒,此时我的头脑很清醒,完全没有起床困难症。我换好衣服,到吧台给自己倒了一杯热水,喝完之后又倒了一杯,很快我的肠道也开始工作,没过多久就进了厕所,并且在两分钟内走了出来,现在身体很轻盈。我洗完手,开始给自己冲咖啡。理想情况下,我是不需要咖啡因来提神的,但至少对现在我的来说,给自己冲咖啡这个动作是我生活的支点。我总觉得,早上要喝的应该是中度或深度烘焙的咖啡,没有太多需要我细细品味、扰乱思绪的风味。

此时我应该能够忍住查看社交媒体和电子邮件的欲望,开始对照前一天晚上列好的待办清单工作。从七点半或八点开始,直到早上十一点左右,我应该就完成今天需要做的所有事情了。据说对于脑力工作者而言,早晨是效率最高的时间段,我自己的感受也的确如此。如果能在头脑最清醒的早晨不受打扰地完成所有工作,剩下的时间就可以留给兴趣爱好、朋友和恋人了(是的,既然是理想的日常,那我应该有一个恋人),并且不会在这些时间里受工作打扰,把生活的秩序搅得一团乱。

十一点半左右,我应该出门赴约中午的饭局。我理想中的内层交际圈,或者说最亲密的那些朋友,他们的数量加上我应该是四人。在四个人的局里,不需要有人一直说话带动气氛,也很少出现其他人话太多导致某一个人插不上话的情况,最安静的人也能在这样的场里待得很舒服,前提是四个人中没有话痨。此外,有很多我喜欢的桌游,玩家数量上限是四人。唔,如果要谈理想的话,这四个人之中,有一个应该是我的男友,不过,我真的很难想象他是什么样子呢。

在某些日子里我可能会和朋友们去桌游店一直玩到晚上,甚至一起在店里点外卖吃饭。桌游比起电子游戏,给我带来的互动感会更强,但也不至于像其他聚会游戏那样过于亲密。不过,在这个理想的一天中,滥用时间是不明智的。吃完午饭后,我就应该和朋友们分开,回到家里给自己冲当天的第二杯,也是最后一杯咖啡。午后的咖啡应该是浅度烘焙的,日晒处理法,有浓烈的水果或花香,在降温后有持续的茶感,可以品味好久。

口腔中还有咖啡的回甘,我开始查看联邦宇宙和 RSS 更新,照顾我的另一个交际圈,看看离我很远的其他地方发生了什么事情。然后是查看电子邮件和即时通讯软件的消息,这个时候我应该收到一些我关注的产品和游戏的新闻报、一些读者的留言、一些求助或询问、联系紧密的网友的消息,这些消息加起来应该不会给我造成太大的负担,不会让我产生推迟到第二天再处理的倦怠感。这些与真实的人的连接应当是令人愉悦的。最后,我会选择一些内容,放到下一期的周刊里。

当我从网络中抽身后,时间应该是下午四点半左右,此时我在电视机前铺好了瑜伽垫,开始当天的锻炼。在这个理想的一天中,我的训练计划应该恰好没有排到力量训练,而是比较轻松的有氧(虽然做 HIIT 也不算轻松,但会让人觉得快乐),结束后略作休息,就开始十五分钟的拉伸,拉伸完毕后是洗澡,此时我的身体应该像刚出生的婴儿一样舒适。梳洗好自己过后,时间是五点半左右,应该开始准备晚餐了。

同样地,在别的日子里,我可能会从零开始买原料,做好几道工艺繁琐的菜,但在这个理想的一天里,冰箱里应该有一些容易处理的食材,或者其他人给我送来的,亦或是我自己提前做好的餐食,稍加处理之后,应该就能在六点左右摆上足够丰盛的晚餐。用餐时,我会和男友一起看《老友记》或者《瑞克与莫蒂》——是的,在理想的日子里,新片子是不被允许的。

晚餐后很适合散步消食,两个人要是能在江边或者海边漫游,应该会很浪漫。我有时会觉得,走出家门散步才是真正的旅行,因为没有行囊,甚至连手机都可以不带,身上没有任何负担,心灵上没有任何束缚,两个人之间也没有任何枷锁,只是在呼吸着、行走着、生活着。漫步也是思考和交谈的绝佳时间,可以消化和整理当天发生的事情,兴许是在餐桌上朋友的小动作,或者是互联网上的见闻。一个人思考可以整合认知,两个人交谈,则可以提供情绪支持,总之是很健康的处理信息的方式。此时路边应该会有跑步的人路过,如果是长相不错的男性,我和男友会有些不道德地一起欣赏,至少在我的想象里,这是作为同性恋者的好处之一。

回到家时大概接近八点了,这个时候我会回到书房里读书,兴许是一本觉得不错,便继续往下读的新书,或者是一本觉得很棒,所以捡起来重读的旧书,又或者,是一本初见便爱上的书,一边读一边想象自己几年后再次打开这本书重读时的感受,这本书的名字或许是《不可承受的生命之轻》。或许,在那个理想的日子里,我会庆幸自己早已体会过了生命中的轻与重、灵与肉,不会陷入托马斯、特蕾莎和萨比娜的苦痛。矛盾的是,在我的想象里,那时的我依旧年轻。

放下书本后,我会开始写作,但愿博客的名字还叫「极客死亡计划」,也但愿我能在上床之前发布文章,因为我不喜欢把草稿晾在 Git 仓库里的感觉。兴许这是一篇前几天写完了一半的草稿,又或许我写得十分顺畅,不需要做太多考究也不需要斟酌,只需要倾泻所思。合上电脑后,我会开始写日记,并依照周计划,写下第二天的待办清单。此时的时间应该是十一点,我钻进了被窝,依偎在爱人的怀抱里睡去。

只可惜,时间好像有些不够用呢。读书与写作这两件事情,对我来说是没办法在一两个小时内完成的。如果我没办法在不压缩睡眠的情况下做完我想做的事情,这又怎么能叫作「完美的一天」呢?我不禁思考,这样理想的日常,真的存在吗?

不过理想就是因为不能存在于现实中,才有美感吧。

是时候回到现实中的生活了。


  1. 事实:凌晨四点时大脑的状态比喝醉了酒还要差。 ↩︎

Jack,你也健身吗?

某种程度,英语里的 Jack 是很传奇的人名,它无处不在。

Jack 是不会说英语的中国人也耳熟能详的英文人名。著名俚语词典 Urban Dictionary 上有 864 页与 Jack 有关的词典(虽然这个网站也以胡说八道的词条居多著称)。令人费解的是,很多工具也以 Jack 命名。如果在公路旁边看到有人举着牌子,牌子上写着「Need a Jack!」,这并不是在说「需要一个男人」,而是说「需要一个千斤顶」;建筑工人用来在地上打孔的冲击锤,叫作 Jackhammer;一种用来脱靴子的工具叫作 Boot jack(反过来,Jackboot 是一种军靴)。

更怪的是,Jack 还和「偷窃」有关系:Hijack(劫持)、Carjack(偷车)和 Skyjack(劫机),Jack 本身作为动词就是「偷」的意思。想必不用我说,一些读者也知道 Jack off 是「手淫」的意思,与 Jerk off 同义。扑克牌里面的 J,也叫 Jack。除此之外,还有 Jack-o-Lantern(南瓜灯)、Jackpot(头等奖)、Lumberjack(伐木工)、Jackrabbit(野兔;兔属;甚至还有一个 Java 内容管理库叫作 Apache Jackrabbit)、Jackass(公驴,也用来骂人)、Jackdaw(寒鸦)、Blackjack(二十一点,一种纸牌游戏)、Applejack(一种苹果酒)。

Jack 的身影遍布这门语言的各个角落,不过今天的文章只会关注其中的一小部分,即健身房里的 Jack。看到 Jack 以各种工具名称出现之后,把它当作动词的用法突然就形象起来了,要么是把什么东西撬起来,要么是把什么东西冲破。带着这个印象,我们来看看以 Jack 命名的各种健身体式。

跳跃吧,杰克!

开合跳的英文单词是 Jumping Jack,在英国叫作 Star Jump(星星跳,还挺形象的)。美国军队管开合跳叫 Side-straddle Hop,直译过来是「侧跨跳」,显然,这个名字更准确,中文里的「开合跳」也从另一个角度准确地描述了这个锻炼动作。如果你从没做过开合跳,可以参考下图。1

正在做开合跳的小人。

所以,明明有更准确的用词,为什么要用 Jack 这个毫不相关的人名呢?英语本身就是 语言界的最大缝合怪 ,再加上 英语的表意效率低下 ,非常依赖言外之意和黑话,有了 Jumping Jack 这类简短的表达,没人会折磨自己的舌头去说 Side-straddle Hop 这类词的。

不过,为什么一定是 Jack?隔壁 John、Dick 和 Tony 不是也广为人知吗?

有一种玩具叫作掷距骨2(Knucklebones),是一种古老的游戏,在许多文明里都能找到类似的变体,简单来说,是一种把小物件(例如骨头、石子)丢起来,然后抓住的反应力游戏。在比较现代的版本里,这种玩具用金属制成,长得很像三维的直角坐标轴。不过,如果不仔细看的话,这些小东西就很像把手脚都张开的小人,就有点像做开合跳时,手脚张开的样子。

这种用来抛的金属小玩具,名字叫作「Jack」。

所以,有没有可能是有人根据这个动作联想到了用来抛掷的这种 Jack,所以才想出了 Jumping Jack 这个名字呢?

很遗憾,不是。根据 维基百科 ,开合跳据说是西点军校的一位军官发明的,他的名字叫作 John Joseph Pershing,他还有一个昵称,叫作「Black Jack」。他作为西点军校指导员的时候,由于非常严格且死板,学员们很不喜欢他。由于他在美国第 10 骑兵团服役过,而这个兵团一开始是作为隔离的黑人单位组建的3,所以学员们给他起外号叫作「Nigger Jack」,后来,这个称呼被弱化成了「Black Jack」4,因为 Nigger 是对黑人的歧视性用语。

所以,因为发明这个运动的军官外号里有 Jack 一词,开合跳也就被称作 Jumping Jack 了?

很遗憾,不是。至少,根据维基百科的说法,Jumping Jack 取自一种玩具的名字(是的,还是玩具)。这种玩具的名字就叫作 Jumping Jack ,在前几个世纪流行于英国、法国和德国等欧洲国家,是一种用木头制成的、有关节的小人。只要拉动小人身体下面的一根线,它的四肢就会动起来,就像是在做开合跳。

Jumping Jack 还有多种变体:Power Jack 要在跳出去的时候做深蹲动作;Squat Jack 则是要在开和合的过程中一直保持半蹲姿态;Half Jack 是幅度更小的开合跳;5Alternating Jack 或者 Scissor Jack 是在保持开合跳手臂动作不变的情况下,左右脚前后交替跳跃。总之,在健身领域,Jack 差不多已经是开合跳的代名词了,各种类型的开合跳都有 Jack 的名字。

亮剑吧,杰克!

Jackknife 是一种核心训练动作,躺在地上,把手臂和腿伸直,往上举,向身体中间靠拢,直到四肢并拢。如果核心力量较弱,身体条件不允许,一些 Jackknife 的变体并不要求手和脚一定要靠拢,只需要核心发力,将四肢支撑住就好。

图源: Jackknife (exercise) - Wikipedia

不同于 Jumping Jack,Jackknife 的词源很明确,这个词的本意是「折叠刀」。如果把人的核心想象成转轴,上半身想象成刀刃,下半身想象成刀柄,把手脚在空中并拢的动作,就像是把折叠刀折起来的动作。

所以,真正的问题是:折叠刀为什么叫 Jackknife?

没人知道。

我翻遍了维基百科、Wiktionary 和 Etymonline,都没有给出确切的词源描述。不过,我倒是误打误撞地在一个讨论刀的论坛6上找到了 相关的讨论 。2013 年,有个叫作 Jack Black7 的网友引用了某个如今打开已经是 404 的网页:

Jackleg is a U.S. southern slang adjective meaning unskilled or unqualified. The term almost certainly comes from jackleg knife (jackknife) and was probably originally used as jackleg carpenter, a carpenter with only the most basic set of tools.

Jackleg 是美国南方俚语,意思是「未受训练的」或「不合格的」。这个词几乎可以肯定源自 Jackleg Knife(Jackknife),有可能最初被用在「只有一把折叠刀的木匠」(jackleg carpenter)这个词上,指代只有最基础的工具的木匠。

所以,Jackknife 最初应该是 Jackleg。 Etymonline 也在 Jack-knife 相关页面中提到了 Jackleg 这个词,里面提到苏格兰方言里有 jockteleg 这个词,也是一种折叠刀,但词源不明。

折叠刀不仅衍生出了一种锻炼的名字,还衍生出了别的含义。作为动词,Jackknife 表示把东西从中间折叠起来(我真服了,你们就不能老老实实用 Fold 这个单词吗?)。Jackknife 还是一种跳水动作,和核心训练动作很像,也要把手臂靠近腿部,将身体折叠起来。

Jackknife 还是一种口语表达:如果一辆卡车发生意外,车头朝向一个方向,而车厢朝向另一个方向,两者形成的角度过小,就像是折叠起来了,这种事故就被称作 Jackknife,这个意思也可以做动词。

Before I knew what was happening, I’d jack-knifed the truck.

我还没意识到发生了什么,我已经把卡车撞成折叠刀了。

不过,我还是不知道折叠刀和 Jack 到底有什么关系!

波巴和奇奇,杰克向你问好!

有一类难以解释的语言现象叫作 Bouba/Kiki 效应 。观察下面两个图形,凭借直觉选择,你觉得它们哪个叫 Bouba,哪个叫 Kiki?

我觉得他们都叫 Claude

全世界的人类都有着相同的倾向,大部分人都会觉得那个圆圆的图形叫 Bouba,而尖尖的图形是 Kiki,人们会把声音和图形联系起来。神奇的是,最近 新发表的一篇研究 发现,雏鸡也存在 Bouba/Kiki 效应,小鸡崽在听到 Bouba 的声音是会自发选择圆润的图形,听到 Kiki 时会选择带尖角的图形。

我在猜测,人们之所以把没有实义的人名 Jack 用在这么多地方,也可能是因为 Bouba/Kiki 效应。至少对我而言,Jack 这个词的发音很容易联想到插、打、锤、砸等动作,比如把长条状的工具插进汽车车窗里,借此把锁撬开偷车的动作(联系到「偷窃」的意思),或者把铁条插进脚和靴子的缝隙里,借此拉开距离,方便把脚从靴子里拿出来(联系到 Boot jack 这个词)。

我在做卷腹的时候,也能感觉到自己不是在轻轻地卷,而是在「Crunch it!」,Crunch 这个单词的发音也带有一些微妙的力量感。这种感觉很难描述清楚,就像很难用语言和逻辑解释为什么圆圆的图形叫 Bouba 而不应该叫 Kiki 一样。

不过,Jackrabbit、Jackass 和 Jackdaw 的用法,应该是把 Jack 这十分常见的男子名当作「雄性」的代名词了,用来表示公的动物,与上述语言现象无关。


就到这里吧,在电脑面前翻各种网页,坐了一两个小时,还吃了夜宵,现在要站起来做几个开合跳才行。


  1. 真的很难忍住不在这里放一张「Happy~ Happy~ Happy~」的 GIF 图。 ↩︎

  2. 我印象很深刻,因为《咩咩启示录》这部我很喜欢的肉鸽游戏里就有「掷距骨」小游戏,虽然和现实中的掷距骨有很大不同。现实中的掷距骨参见: Knucklebones - Wikipedia  ↩︎

  3. 参见: 10th Cavalry Regiment (United States) - Wikipedia  ↩︎

  4. 参见: John J. Pershing  ↩︎

  5. 参见: Jumping Jacks - Wikipedia  ↩︎

  6. 叫作 Blade Forums ,很神奇,互联网上居然存在这么小众的论坛。 ↩︎

  7. 这名字…… 你该不会是黑杰克军官转世吧? ↩︎

如何获得内心的安宁

和仲树老师译的《 如何从敌人身上获益 》属于同一系列的书籍,这本是塞涅卡的《道德书简》的选译本,书中收录了 41 封这位斯多葛学派哲人与门徒路奇里乌斯的书信。每一篇书信的篇幅都不长,读起来还算亲切。书中不乏普通人都能读懂的精彩论述,主题有关友谊、社交、焦虑、饮酒、阅读、老年、死亡和哲学。要说缺点的话,由于是书信体裁,不可避免地有些「散」,读起来鲜有畅快的感觉。此外,塞涅卡的论述对如今的很多人而言,可能有些爹味。

这本书所属的系列《索菲亚文库》,由上海文艺出版社出版,似乎是专门为大众设计的哲学书系列,选译的都是著名哲学家的那些不太著名、但易于读懂的著作。知识精英时常摆架子,把文字弄得一般人难以接近,这个图书系列试图把哲学带给普通人,尽管内容可能缺乏深度,但态度令人赞赏。在塞涅卡的书信中,有一个常见的主题就是「哲学家和大众的关系」,他的态度也算是亲民的。

需要注意的是,后文出现了很多书信的标题,例如《朋友间应当无话不谈吗?》,这些标题并非塞涅卡所写,而是译者加上的,书信本身没有题目。

什么是「内心的安宁」?

在本书中反复出现的哲学思想是,塞涅卡认为一切可以被失去的东西,都不是自己的。他认为,为了迎接命运可能带来的一切打击,要学会提前做好思想上的准备,即预设「一切都有可能发生」,并且「一切也都有可能不会发生」,如此一来,无论命运给自己带来什么灾难,自己都能先其一步,不会感到意外和震惊,如果早已做好了准备、已经接受事实,继而也不会感到痛苦。

在谈到财富时,尤其如此,不应该为失去财富而感到痛苦。然而,塞涅卡认为,也不应该把财富视作负担。

把财富视为难以忍受的负担,是心智不够沉稳的表现。

——《哲学家应该如何生活?》

往后也探讨了如何面对死亡,态度如出一辙。

既不厌倦生命,也不畏惧死亡。

——《如何应对病痛?》

死亡从不计较年岁。我们无法知道它会在哪里等着我们。因此,你应当随时随地都准备好迎接他。

束缚我们的,只有一条锁链,那就是对生命的热爱。我们并不需要彻底摈弃这种热爱,但必须学会适度削弱它。

——《如何面对死亡?》

削弱对生命的热爱,从某种角度来看,就是「节制」,而「节制」也是我印象中的古典哲学常讨论的主题,在塞涅卡的书信中也反复出现。在《如何通往哲学?》这封书信中,他表示:「在某些情况下,相比于有节制地加以控制,彻底戒掉反而更不需要意志的努力。」这不难理解。如果一个人从没吃过精加工食品,就不会渴望冰淇凌,而戒断之后,过不了多久就会恢复到近似于「从没吃过」的状态,忘记此类食物的味道;而「有节制地加以控制」,意味着人会被不断地提醒冰淇淋的味道,从而更难抑制渴望。

在我看来,节制也是获得内心安宁的重要因素。不能因为学习哲学,就把财富等外物视作负担,继而表示鄙夷,或者惴惴不安,担心财富会让自己变成道德败坏的人;另一边,挥金如土自然是值得鄙夷的,塞涅卡在书信中也反复批评当时罗马有钱人的各种风气,比如不用某种材质的砖块修浴缸就没有办法洗澡等等。学会有节制地使用财富才是健康的生活方式。我也在女性主义相关的内容种听到这样一种观点,大男子主义,或者说有毒的男子气概(toxic masculinity),实际上是拥有「力量」却不能有节制地加以控制,真正成熟且值得尊敬的人(不只是男性),是拥有力量且不滥用力量的人。

总的来说,在我的理解里,塞涅卡所认为的「内心的安宁」是通过智慧(学习哲学并践行)获得的,其中的关键就在于为一切做好准备,不让不幸影响自己,同时做到节制,过朴素的生活。

什么是友谊?

塞涅卡对「朋友」这个称呼的使用门槛很高,和大众使用这个词的方式不同,不是所有相互认识且有所交流的人都能被称作「朋友」。他认为朋友之间应该无话不谈,与朋友的关系应当是忠诚且(在某种程度上)亲密的。不满足这些条件,让自己有顾虑的人,在一开始就不应当纳入「朋友」之列,应当在成为朋友之前审视对方,判断此人是否应该纳入自己的社交圈子。

赫卡托说过:“我将为你展示一种没有掺杂药物、草药或巫术的爱情秘方。这条秘方就是,如果你希望被爱,那就要去爱别人。”

——《哲学家渴望拥有朋友吗?》

自己不爱的人当然也没必要建立关系。读到这里的时候,我就想起我认识的人中,有人会声称自己有不少「工具朋友」,或者说是做某件事情的「搭子」,因为自己容易寂寞。我想塞涅卡是不会赞同这种人际关系的,友谊不是用来消解孤独感的工具。对我而言,社交本身就是耗费精力的事情,与其费劲维护浅层的关系,不如多去关注那些值得去爱的人。不过,有人告诉过我,现代社会有必要维护一些浅链接,也就是所谓的「人脉」。我想,要得到这种功利主义的好处,就必须付出亵渎友谊之名的代价吧,就看个体怎么抉择了。

“交友是为了在自己生病时有人前来陪伴,或在困顿遭囚时有人前来施以援手。”恰恰相反,他可能首先需要自己去陪伴在他人病榻之侧,或在友人落入敌手时予以营救。若某人只考虑自身利益,并以此为目的去寻求友谊,那就大错特错了。

——《哲学家渴望拥有朋友吗?》

话说回书本内容,塞涅卡还批评了人们对「智者自足」的误解。一些人觉得智者,或者说哲学家,不需要朋友。塞涅卡说他们并非不需要朋友,而是即便在没有朋友的情况下,也能感到满足,并且能忍受失去朋友之痛,因为智者总是满足于自己所拥有的一切,而愚者都因为不知足于此,而深受困扰。简单来说,他认为哲学家1不会因为没有朋友或失去朋友就感到痛苦,但仍然渴望建立美好的友谊。

在《如何与朋友分享知识?》中,塞涅卡描述了他心目中友谊的样子。他认为朋友应该共同生活,甚至共同起居,观察其言行,才能产生真正的影响。塞涅卡认为,友谊和爱情是相似的,甚至是比爱情更高尚的情感。没有人会因为利益或别的原因坠入爱河,对待友谊也应该如此。

关于哀悼

在《如何缅怀故去的朋友》中,塞涅卡批评了让丧友之痛占据自己的那些人,他甚至这样写道:

在泪水中,我们其实想向别人证明,自己确实是在悲痛。这不是因为我们悲痛到无法自抑,而是因为我们想展示悲伤。没有人会哀悼给自己看。唉,这多么可悲,也多么愚蠢——连悲伤之中,竟也暗藏着炫耀。

我和一些同龄人聊天时,他们表示,在参加与自己关系很亲近的亲人的葬礼时,他们哭不出来,没法像那些大人一样哭丧。其中有一个,在葬礼的一年后去到她奶奶的坟前,才意识到那里躺着的真的是她奶奶,那个时候她才躲到角落一个人哭了好久。另一位,由于是女性,所以不被允许送丧,和其他女性长辈待在一起时,她也无法哭泣,显得格格不入。

我又想起安德烈·纪德说的话:一切需要言说之事已经被说过了,但由于人们会忘记,所以一切都需要被重新言说。不少道理和思想早在几百年前就被伟人阐述过了,而如今的人们还需要被不断地提醒这些属于全人类的思想。不过,这还涉及哲学与大众的关系,后文会提到。

对于一个明理的人来说,仅仅因为时间迁移,才让悲伤得以“痊愈”,未免显得可耻。我更希望的是你主动放下悲伤,而非等着悲伤慢慢离开你。

这就是对追求智慧之人的更高要求了。塞涅卡似乎非常在乎「主动」这回事,包括面对死亡,他也探讨「何时应该主动结束生命?」,并认为赴死是英勇之举。抛开心理疾病不谈,在塞涅卡眼里,自杀是宣告自己对生命的主导权的一种方式。连死亡这件事情,都要自己决定,而不是被命运推着走。

心理健康

旅行能帮助消解焦虑和沮丧吗?塞涅卡引用苏格拉底的话这样回答:

“你把自己也带上了路。旅行对你无益,你又有什么可以惊奇的呢?你背负的包袱,正是驱使你离开的原因。”

塞涅卡认为,如果心灵没有改变,见识再多的新景都没有用,反而会因为四处奔波而加剧折磨——必须先放下心灵的重负。

你到何处并不重要,重要的是,你在抵达时,是一个什么样的人。

——《旅行能帮助消解焦虑和沮丧吗?》

不过,要如何放下心灵的重负,要如何卸下让自己焦虑和沮丧的包袱呢?这点其实可以回到前文对「内心的安宁」的阐述中去回答。塞涅卡还认为,应当把全部心灵都献给哲学。

灵魂上的病症越是严重,反而越感觉不到情况有多糟糕,只有哲学才能唤醒心灵,消除心灵上的痛苦。哲学不是闲暇时才学一下的东西,应该是生活的主宰。哲学会对其他一切事务说:“我不是来接受你们所剩下的时间,而是来决定给你们留下多少时间。”哲学的力量可以挫败命运的一切打击。

——《为什么应该将全部心灵献给哲学?》

与「旅行」相关的还有「隐居」,都是地点的迁移。塞涅卡真的很强调「心灵」,他认为能否获得内心的安宁与居所无关。我也有所思考,春节期间回到家时我总感到不舒服,我也在思考自己对故土为什么没有强烈的情感,我还在想未来要到哪里去定居。我想,我或许不需要去往另一个地方、另一个家,去到哪里并不重要,也不必纠结自己对故乡的感情,把注意力放在心灵的培育上就好了。退回到自身当中,与自己成为朋友的人,永远不会孤单。

唯有当以一切声音都无法触动你,一切言语(无论是威胁、引诱,还是周遭无意义的喧嚣),都不能动摇你的时候,你才可以确信,你终于能“安然就寝”。

——《远离喧嚣就能获得内心安宁吗?》

不过,这可不容易,也不「正常」,大众会感到不解。即便在「短视频有害健康」几乎要成为共识的今天,我身边的人仍然会在得知我的手机里没有安装抖音也没有安装哔哩哔哩时感到惊讶,好奇我「平时都在干什么?」——写代码和读书啊?还能干嘛?

接下来要讨论的话题,就与大众有关。

哲学与大众的关系

之前在 Owen 的博客 里看到了《良好生活的哲学》一书的读书笔记,读了几页,没有读完,但我对开篇的几句话印象深刻。那些句子的意思大概是:如今要是有人在读了哲学家的作品之后,真的像哲学家一样生活,会被人当成怪胎。换句话说,人们认为实践哲学是不正常的。

这便是哲学与大众的关系之写照。如今人们似乎把哲学贬为一种用来研究的文学(塞涅卡也批评了语文学家),研究某某哲学家的思想、观点和生平,却很少真的像哲学家所倡导的那样生活。实际上,哲学与大众的矛盾,在塞涅卡那个时代也有出现,人们容易把哲学家当作生活方式与他们完全不同的人,对他们敬而远之。

塞涅卡这样写道:

哪怕我们以最谦卑的方式去追求哲学,哲学这个名字也仍然不甚得人喜爱。设想一下,如果我们还要刻意背离社会上的常规礼法,人们会作何反应?我们的内心深处应当与众不同,但外在表现则要与大众保持一致。我们的衣着不应华丽张扬,但也不要邋遢寒酸。我们不应该使用镶满纯金的银器,但也不应该把弃用金银当作过俭朴生活的标志。我们的目标是过上一种比大众更好的生活,而非与大众截然对立。

——《哲学家应该如何生活?》

即便选择了过着受哲学指导的生活,人也无法避免与大众打交道。那些在努力塑造健全的人格的人,在面对声势浩大的种种恶习时,往往也难以抵御。我举一个现代的例子,一个正在减肥的人往往难以回绝朋友的宴请,而就算他真的忍住不吃,也很容易收到这样的评价:「像你这样生活好累啊」「生活已经这么苦了,为什么要这样对自己?」「你太厉害了,我是不行的」。在我看来,这和哲学与大众的矛盾如出一辙——减肥何尝不是节制的哲学?

在古典哲学的视角下,大众的不少行为都可以被称作「恶习」,与其所倡导的「美德」相对。这种对大众的批评,放到现代语境下是不恰当的,因没人喜欢被称作「恶人」。关于古典哲学与现代哲学的区别,可以阅读第 42 期周刊中的《 古典审美与现代审丑 》一节。

以下的引文,读者把其中的「恶人」「恶习」当作古典哲学家对自身的要求就好。

不要因为恶人众多,就变得和他们一样,也不要因为大众与你不同,就与之为敌。尽可能退回你自身之中,与能促使你进步的人交往,欢迎那些你能使之进步的人。

——《如何避免大众对我们的不良影响?》

所谓的「退回到自身之中」,也与前文塞涅卡对「心灵」的强调呼应。在我的理解里,这句话的意思就是不要从别人身上找答案,应该如何生活,这事应该由自己决断。至于如何做决策,可以从哲学里找答案。

定义了「大众」,我觉得有必要定义一下文中的「哲学」一词,可能与如今大众的理解有所不同。

从后文的论述来看,塞涅卡把哲学当成最高级的学问,他甚至还在《自由教育和自由技艺能培养好人吗?》中表达了对几何学家等学者的鄙夷,他觉得学习数学没有用处。

你们这群几何学家,能计算圆的面积,能把任何形状都化为面积相当的正方形,能测出星辰之间的距离。好吧,如果你们真是行家,请测量一下某个人的灵魂,告诉我他的灵魂是大是小。你能定义何为一条直线,但如果你根本不懂“正直”在人生中的意义,给出这个定义又有何用?

塞涅卡或许是历史上第一个读书无用论的倡议者。

他后面还批评了天文学(虽然听他的描述,他指的应该是占星术),这里就略去了。他认为学习自由技艺,比如几何学、天文学、音乐、厨艺等等,是没有实际价值的。之所以要让孩子接受这种教育,在他看来,不是因为这类教育能让他们成为道德高尚之人,而是因为能让他们的心智为培养美德做好准备。

要理解的是,在古罗马,数学可能真的没有用处,不像现在得到了如此广泛的应用。塞涅卡再有远见,也无法预见几百年后的变化。如果从现在的视角理解这段话,可以把它理解为「相对」于个体的。在塞涅卡看来,哲学,即培养美德、帮助个体好好生活、对人生有长远意义的知识,才是最终目的,所谓的自由技艺只是「有点用处的不务正业」,成年人不该花费大量的时间在其中。对现代人而言,大概可以把自由技艺理解为「业余爱好」。

无论怎么理解,「如何好好生活?」以及「什么样的生活是值得过的?」难道不应该是任何时代的任何人都应该思考的问题吗?而这个问题的答案,就是世世代代的哲学家们试图回答的。

窥探敌营与打破信息茧房

塞涅卡所属的学派是斯多葛学派,但他却经常在书信中引用伊壁鸠鲁。伊壁鸠鲁学派主张享乐(当然,与现代人口中的享乐主义完全不同),而斯多葛学派主张禁欲。塞涅卡阅读伊壁鸠鲁,自称是为了「打探敌营,知己知彼」。

此外,他还宣称这些有价值的思想(或者说真理)是属于全人类的,而不是属于某个派别,他只是在使用属于全人类的财富。这个观点我很喜欢,说实话,我读哲学书籍时,常常想搞清楚自己更倾向于那个派别,但转念一想,自己只是在探索人文2,完全不必要急着给自己下标签。塞涅卡的思想有很多我也不赞同,但我也能从这位伟人身上学到很多东西。

塞涅卡在《如何阅读?》中写到,阅读不应该走马观花,要忠诚地阅读一位作者,参透他的思想。这种忠诚也没有让他陷入到信息茧房中,整如前文所说,他时常阅读与自己观点完全相反的人所写的东西。我想,这对现代人来说仍然是很好的榜样。

论写作、文风和演说

塞涅卡在《社会风气如何影响文风?》中论述,言如其人,心灵、人格和人品都会体现在文风和说话方式上,因此要保护好自己的心灵。如果文风开始堕落,说明社会风气也开始堕落。

什么是好的文风?塞涅卡的观点大致可以这样总结:不刻意回避日常表达,不堆砌辞藻,也不至于平庸无奇;在编排上,流畅平稳,遵循惯常的节奏感。

在《哲学家应该如何演讲?》中,塞涅卡批评了那些讲话速度飞快的人,他认为这事不知廉耻的表现,因为说话速度快必然会出现脑子跟不上嘴巴的情况,说得快是因为根本不在乎自己说了什么。语速极快之人,容易说出自己都不认同的话,过度关注修辞,哲学的高度也被拉低了。慢吞吞也不行,简单来说,讲话应该平缓自然,一边讲话一边反思内容是否正确。

在《格言警句有用吗?》中,塞涅卡教育了门徒,认为他不应该要求从他那里获得更多的格言警句,因为那些句子之所以凸出,是因为周边的句子平淡无奇。塞涅卡常常引用伊壁鸠鲁的名言,却很少引用自家学派的警句,是因为:

无论阅读哪部作品,都能发现值得称道之语。只不过这些句子并不显眼,因为周围的其他内容同样水准很高。

他还认为,一个已经有一定积累的人,应该能够独立思考,自己写出这样的句子,而不应该一味地背诵别人写的句子。

讲完文风、演讲和警句,和写作以及思考相关的,还有一个观点。塞涅卡认为逻辑推理是繁琐无用的。这个值得拿出来好好讲一讲。在《哲学与逻辑诡辩有何区别?》,他的观点大概是说,直接简单的真理才是好的,不应该去学习逻辑推理,他在书信中反复批评了三段论推理的可笑之处。我想,他的意思是,应该要关注真理的内容,而不是真理的形式。

我的想法是,大概只有无法在观点和想法层面给出回应,却觉得不爽想要攻击,才会去纠结逻辑结构。把对方的观点定义为滑坡谬误之类的名字,哪怕原句根本就不是在给出结论。大部分错误的想法,不需要分析其逻辑就能击破。

我在想,逻辑究竟是「内容层」还是「结构层」的东西?内容层即想法和观点本身,而结构层则和语言、用词、句法等归为一类。逻辑学似乎是夹在两者中间的东西。不过这就不是这本书的内容了,还是改日再谈吧。

塞涅卡的「爹味」从何体现?

说了不少好话,我也的确学到不少,尤其是大众和哲学的关系、内心的安宁等,对古典哲学的理解也更深入了一分,那么,是时候来说点不好的了。

我记得我某天晚上在读这本书的时候,刚翻开一页,就读到一句让我直接笑出声的句子。

亲爱的路奇里乌斯,沉迷于锻炼肱二头肌、扩展肩宽、增加肺活量,这种行为实在荒唐,有教养的人不会干这种蠢事。

塞涅卡还说,再怎么锻炼,人都比不上一头牛的力量。他坚信,并且在后文中反复提及,锻炼身体,让身体变得强壮,必然会压迫精神。在他眼里,心灵和精神是最重要的,心灵的健康应该放在身体健康之上。在其他书信中也能读到相关的内容,他觉得运动和锻炼就是为了让身体劳累,他说,他年老时只需要进行最简单的运动,就能达到劳累身体的效果。

那些醉心于身体锻炼的人,要忍受诸多烦扰。首先是锻炼本身就劳神费力,让人筋疲力尽,无法集中精神或从事更艰难的学习。其次是过量进食,这会让人心智迟钝。再次,他们还得请来一些最下等的仆人做教练,这些人不是在涂抹油膏,就是在灌酒。他们所谓美好的一天,就是出一身大汗,然后空腹饮酒,好让身体更快吸收丢失的水分。出汗加饮酒,这是会让人的胃病的生活方式!其实,有一些简便有效的锻炼方式,可以迅速让身体疲劳,又节省时间,而时间正是需要精细打算的资源。

用最简单粗鄙的话评价塞涅卡对于锻炼的观点就是:菜就多练。事实上,锻炼会让身体分泌多种激素,例如去甲肾上腺素,有助于提升警觉性,促进记忆的形成和获取,让大脑集中注意力。3显然,这对学习是有帮助的。我自己的体验也是,锻炼过后进行脑力工作,会感觉更容易集中注意力,效率也更高。

我猜想,塞涅卡之所以认为锻炼身体劳神费心、无法集中精神,是他自己的身体太差,继而导致他的锻炼体验不太好。塞涅卡也主张朴素的饮食,光是水和面包等最简单的食物就足够。吃得不好,营养不均衡,也不能获取足够的能量,锻炼表现自然不好。

当然,塞涅卡所处的时代是没有这些生物学知识的(更何况他本人还认为哲学是最高的学科,嘲弄几何学家,如果有生物学家出现,估计也入不了他的法眼),他对锻炼有这些误解也正常。用自身局限的经验做出不正确的判断,是任何时代的人都无法避免的,哪怕是哲学家。

读到这里,读者可能会猜测塞涅卡是一个大难当头都还要讲大道理的爹味哲学家。事实也的确如此,塞涅卡最终被判处死刑,暴君要求他自杀,他割腕过后也还在生命的最后时刻发表演讲,并指责那些为他感到悲痛而哭泣的朋友,质问他们的哲学去哪了?他们多年来为应对厄运所锤炼的坚定意志去哪儿了?

现代人固然可以评价塞涅卡爹味,但或许我们应该允许拥有智慧的人展现出傲慢,而不是要求知识精英为大众弯腰磕头。我觉得,在死亡到临之际还在为自己坚信的东西抗争的人,实在可敬。


  1. 哲学家本意是「爱智慧的人」,这里也可以如此理解。 ↩︎

  2. 这也是为什么我最近(2026 年 2 月)重写 个人主页 的时候,在主页加上了这个描述:「我编写软件、写作,和探索人文」。 ↩︎

  3. 参见: Norepinephrine - Wikipedia  ↩︎

我的乡愁

现在是凌晨 00:55,我还在书房坐着,因为我的门外有一个说话令人讨厌的可悲的小男人跟我爸聊了几个小时,而我一点也不想出去跟他们撞见。

我在校外租房,虽然还没到一年,但已经在住处建立起了生活秩序。因此,回家之前我一直拖延,终于要开始收拾行李时,我似乎出现了躯体化的反应,脖子酸痛,而且头昏脑胀。我在自己的床上躺了好一会儿,才平复心情。走之前,我还对家里的绿植念念不忘。虽然是水培植物,但一个月不换水,真的没问题吗?

如今每次回家,我爸都会想方设法在餐桌上提起我的不念家,这次在我姑姑家,问我表哥,现在回家的时候还会不会有激动的感觉,我表哥说可能有点吧,我爸说,我已经没有了。也不知道是不是圆滑,我表哥说我爸应该感到高兴,因为成功、理性的人就是这样的,不念家——总之我说不出这种话来。我已经接受,这些已经活到四十多岁,还没有受过多少教育的人,本身就不会反思,跟他们讲道理是徒劳无功的,所以,我当然不会冒着起冲突的风险跟我爸解释我为什么不想回家,也没那个必要。

毫无预兆,今晚家里来了十多号人,从六点开始我就听到噪音,下楼之后全是不熟悉的面孔和目光,在自己家里走起路来,还真是不自在。我拿完我要的的东西,逃命回到书房,盘算着要找什么理由溜出去。西西弗的储值卡里正好还有一百多块钱,去那边喝杯饮料,坐一坐。不过,我要怎么在众目睽睽之下把电脑或者书带出门呢,真是难办。

最终还是留下来吃饭了,支撑我到最后的是豌豆苗、豆芽和娃娃菜,不然我早走了。素菜请先上桌,谢谢。

不想引起注意,于是空手出门了,当然带了耳机,一边听歌一边走出小区,走进商圈,在人群里穿梭的时候,我才觉得自己是自由的。我没有目的地,就一直往前走,想着再过一两个小时,家里的人就应该走了。走到一个路口,突然认出了去母校的路,于是就去我的高中故地重游了。不过,我只是在看路边的招牌,看看那些熟悉的店铺是不是还在。看到一家支撑我度过无数个午后的奶茶店和我很爱吃的芝士焗饭还在,心满意足,只不过之前常和朋友去吃的一家鸡公煲不见了,校门口的一家杂货店变成了装修大气的古茗。而我,竟然没有一点怀旧的伤感。

唔,要不是不想破坏吃了很多绿叶菜肚子里很舒服的感觉,我就去买以前爱喝的奶茶了。或许我真是我表哥说的理性的人吧,这种时候,怀旧并不会战胜我对健康的追求。

走回家的时候,听了一期播客,盘算着能不能卡好时间,在播客结束的时间刚好到家。不过没成,离小区还有段距离的时候,巴赫的音乐响起,我直接摘下了耳机。就这样听着城市的声音也挺好的。由于我一年回来不了几次,没有录入小区的人脸门禁,要请保安开门。值班的是我不认识的保安,他问我住哪栋,我迟疑了,思考片刻还给出了错误的答案,不过好在我说的那栋楼也是存在的,没被当成坏人。

到家了,客厅灯光昏暗,我舒了一口气,可随即听到楼上传来男人的声音,我的心又死了。我散步了一个半小时,这个可悲的小男人还在我家里。事实是,三四个小时后,他还在我的房间外面跟我爸说话。

让我来列举一下他一直重复的几句话:「所以我这人生啊,过得还是很好的」「你懂没得?」「谁都比不过我,我谁都不怕」「他不行,他只能排老二」「你懂没得?」「你那个时候小,你不晓得」……

听到门外某个老男人在讲「我的人生为什么没有走到顶峰」,说自己从小就聪明、家里的男性长辈都喜欢他,说自己本来成为亿万富翁都有可能。后面叽里咕噜说了一大堆我没听清,最后得出的结论是:

「所以我这一生啊,都败在我的舅妈」

我很不道德地在书房里笑出了声,哎哟,这种场面怎么没有早点端上来啊,听老男人追忆人生我能笑好久,早知道能看到这种戏码就不出门溜达了。

他还把那句话重复了好几遍,后面还听到几句反复出现的话:「我在部队的时候」「我这辈子就是受到了奸人陷害」「所以我不恨我的舅舅,我就恨我的舅妈」

Ah, pathetic little old man always cheers me up.

—— 我的联邦宇宙账号

本来觉得这个小男人说的话很有观赏性,给我带来的愉悦能比过不少中文播客,不过我很快就听到了别的一些东西。

吃瓜吃到一半听到自己的名字,这小男人倒是很会控制语气语调,在大喊「我这辈子就是被我舅妈害了」这个时候字正腔圆,其他时候低声细气的,没听清说了什么。好像是在我说我这个年纪什么都不懂,叫我干什么就干什么,越来越好笑了。

有的男人真的很喜欢把善良当作弱小呢。

—— 我的联邦宇宙账号

随后这个可悲的小男人还说了不少有趣的话,比如他谈起他的佣人(我想,如果世道允许,他一定会使用「奴隶」这个词),说他过得跟古时候的老爷一样,叫他们打饭就去打饭。他的说话方式真值得品味,因为他在使用「老爷」这个词之前,加了一句「说得不好听点」,但是真说出口的时候,还觉得很得意。

他还谈起我的爷爷。

很有意思,他们开始讨论今天晚上我爷爷在餐桌上说的话。我爸在想办法给我爷爷找补,说他确实不会说话,而这个男人把这个当作某种机会,说「这是因为我舅舅(也就是我爷爷)跟我关系好,不介意这些」。

我爷爷说那句话的时候我在场,大概是有些阴阳怪气地嘲讽了他,说他对自己的前妻不好。我能感到我的爷爷不太喜欢他,只不过用开玩笑的方式给他留了些体面。这个男人当时一直在委婉地表达我爷爷「胳膊肘往外拐」「帮外人说话」,而其他人还在讲所谓的兄弟情义,说「我们兄弟娶谁就认谁」。这个男人给我的印象就是自以为圆滑,立很多规矩,脑子里想了很多没用的东西,一直在想怎么让自己看起来 屌更大 一点(刚才跟我爸讲话的时候,一直在说「你晓不晓得?」,因为他似乎把我爸当成比他小、需要他教育的弟弟),就是不肯坦诚相待。

对我爷爷感受到了前所未有的敬佩,就是在这种时刻。

—— 我的联邦宇宙账号

想起我的爷爷,我记得小时候和他睡一张床,他很喜欢我,孩童时期的我也经常围着他转。长大过后就渐渐不亲近了,他也对我的某些行为有些意见,不过他总是在大部分时候保持沉默,很少干涉我。

就是从这个时候开始,我对门外那个可悲的小男人的态度,从嘲弄变成了厌恶。

他的妻子给他打了两次电话,叫他回家,通话时我爸在旁边,她也就没把话说重让自己丈夫在兄弟面前难堪。如果我的想象力再发散一点,我可能不会把他妻子的好态度解读为圆滑,而是恐惧,那个男人的说话方式完全就像是个家暴男。这个男人,几个小时前在餐桌上谈起自己的前妻,说她割腕流了好多血,把那段经历当作故事来讲,我不觉得他对这任妻子会有多好。

我想我讨厌回家的根本原因,是不想和这类人扯上关系。在这座发展落后、官员贪污的小城市里,人们的心胸狭隘、目光短浅,是可以被理解的。他们话里话外说的都是他们小圈子里的人,谈的是过去乡镇上的事,他们能看到的世界,也就仅限于此了(虽然,出于某种莫名其妙的自信,他们觉得自己很擅长讲解国家政治话题)。我不批评他,但我厌恶他。

这就是我的乡愁——回到家乡时,不可避免感到的忧愁。

❌