玉兰

自我记事起,奶奶的样子就没有变过。

那时不能说身手矫健,但也可算颇为健康。她住在大伯家四楼,每天要上下楼好几次。她每天六七点就起床,喜欢到一楼坐着看外面人来人往,和来作客的邻居们寒暄,有时还会帮忙和顾客们打交道。她喜欢边折大金纸边和人说话,一个下午能折一箱。

听爸妈说,奶奶的脾气其实不大好,时不时喜欢和人吵架。作为孙子的我倒是没有感受到,大概也是隔代亲的原因。偶尔她会和爷爷打冷战,但也是过段时间就好了。小时候家里还有固定电话,每周爸爸都会敦促我们打个电话回去,和爷爷奶奶说说话。从小学到大学,上学的距离一点点远起来,她关心的事情倒是没变。无非是吃不吃得饱、天气冷了要穿衣服、时不时要老家看看。

奶奶养过一只猫。

几年前过中秋回老家和奶奶聊天时我提到以前她养猫的事。我记得在我读小学的时候回老家,每次吃完中午饭大概下午一点半时奶奶就会拿着残羹冷饭,一般会加上一点鱼肉装在一个小铁碗里摇摇晃晃地走到以前的老房子。

那只猫一般已经在那里等着了。

然后奶奶放下碗,坐在一张可能比我还老的凳子上,看着猫吃着碗里的东西,念念叨叨地对着它说个不停。猫当然听不懂奶奶在说什么,但这并不重要。等猫吃完后,它会在那里等一会,直到奶奶要收碗它才离去。至于去哪里?那也并不重要。只是日复一日,它还会在那里出现,然后消失。

我那时还小,有时会屁颠屁颠地跟着一起去。当时对这一幕感到特别陌生,甚至笑奶奶何必对着猫自言自语。奶奶和我说,有时她到点忘了送吃的过去,过了几个小时过去看到猫还在那里等着就会感觉十分内疚,我相信如果猫有灵性,它会理解老人的健忘,它会守着心照不宣的默契,即便奶奶偶尔的忘记,它也会原谅她。

几年前那只猫就去世了,活了十几年。奶奶托人找了块风水还不错的地方,把它埋了。

奶奶也不再去老房子了。

大约是在那之后,奶奶的脑子开始不记事了。经常会把我和哥哥混淆,走到远一点的地方就会不认路。有一次她走到市场买东西,曾经是她经常去的地方,却找不到回来的路,后来是别人发现后送回来的。

她不再出远门了。

于是我们看着奶奶逐渐糊涂。爷爷还在的时候还能和她拌嘴,爷爷走后更是少了一个每天和她说话的人。家里的电话还始终留着,但到后面她也不会接了。

我们每年都会去看她几次。最近这些年她总会和我说相同的一个故事。仿佛她的记忆就停留在那一刻:

我那时刚回到家,刚做饭给孩子们吃。然后哨子马上就想起来了。我立马把一点点很稀的粥给几个孩子吃。自己都顾不上吃东西就马上要出去。啊,那时候肚子天天都是饿的,不像现在大家都有饭吃。

大概是曾经长期肚子饿的经历,她的饭量一直很大。直到今年过年期间,她还每餐能喝三碗粥。即便如此,还是说不够。也是忘了自己喝了多少,总会说刚吃两碗还不让她吃。

一个月前,大伯时不时打来电话说奶奶不吃饭了。开始有点像小孩子闹脾气一样,后面逐渐吃不下了。周五下午奶奶离开了我们去找爷爷拌嘴了,没有经历太多痛苦。她有个漂亮的名字,叫玉兰。

愿她安息。

从写一个 WordPress 插件说起

之前博客的《目录》页面用的是 List category posts 这个插件生成。可这个插件虽然功能比较多,但是不支持(还是我不知道?)我要生成的页面。

再往前用的插件是 Dagon Design Sitemap Generator,它可以生成一个以「分类目录」为主题的文章页面列表(例子可以看文章存档 – 木遥的窗子)。但是这个插件很长时间没更新了,甚至它的官网都打不开了,没办法重新下载这个插件。

考虑到这个插件功能并不复杂,索性自己写好了。我的文章本身不多,因此也不用做分页或者其他的配置,用最简单的方式即可。这个插件应该符合以下功能:

  • 生成一个双层级的 bullet list
    • 以「分类目录」为第一层,排序方式按单词字母正序
    • 以该分类目录下属的文章为第二层,排序方式按文章创建时间倒序
  • 「分类目录」的展示需要加前缀 “Category”,且这个前缀需要加粗
  • 「分类目录」的内容为分类标题,该标题为该分类的 URL
  • 文章列表都是可点击的 URL
  • 文章标题后面增加文章创建的时间

以上功能其实不复杂,最后只用把它们拼成 HTML 语法的代码即可。

问题在于,我从来没写过 WordPress 插件,甚至我也不会 PHP。换在两年前,如果需要完成这项任务我应该需要:

  1. 用至少 2 天时间学习 PHP 的基本语法,其中可能包括:
    • 找到合适的上手文档/教材
    • 搜索无数次 StackOverflow 搭一套可运行环境
    • 学点基础语法,并且在写的过程中反复查文档
  2. 用至少 2 天时间学习 WordPress 的开发过程,其中可能包括:
    • 为了性能和效率,先在本地机器跑起一个 WordPress 页面
    • 从 WordPress 的文档看怎么写出一个 Hello World 插件
    • 搜索无数次 StackOverflow 看别人怎么解决各种意想不到的问题

但是自从有了生成式 AI 后,完成这么一项任务变得无比简单。以这次写插件为例,用的是 Anthropic 新发布的模型 Claude 3.5 Sonnet,前后只用了 30 分钟就完成了。我并没有学 PHP 的基础语法,也没有查过 WordPress 的文档。只需要通过合适的 Prompt 引导 AI 生成合适的代码,同时让 AI 告诉我怎么把插件安装到 WordPress 即可。

当然,初次生成的代码不是完美的,但是把需要改进的内容告诉 AI 即可慢慢引导到正确的结果。

这与程序员目前写代码是一样的过程:刚开始写好的大概率是不完善的,有错误或此前没考虑到的地方,一步步改好重新运行,通过不断的试错达到最终的效果。

这就是 Sam Altman 提到的完全使用自然语言编程。几十年前的程序员写的是汇编语言,而今天绝大多数的程序员都不再用,而是通过 Python 等高级语言(这里的高级并非褒义词,而是高度封装的意思,类似于预制菜和炒菜的区别)完成任务。而如今的 AI 是一个新的编译器,它可以让大多数人直接通过自然语言编程。

或者类比一下,coder 有点类似于国内较早学习英文的人,有能力将中英文互相翻译。而现在的 AI 可以充当一个翻译器,让人可以直接用自然语言和计算机交流。

但这并不意味着编程就成为一件无门槛的事—尽管门槛降低了些。我们依然要整理好需求和思路才能完成任务。以刚刚的 WordPress 插件为例,如果只是说「做一个插件支持以『分类目录』归类展示文章列表」,那么有可能会作出很多不同版本的插件。

事实上,这也是 software engineer 和 coder 的区别。前者更多的工作在于将一个较大的任务拆分成小任务,通过合适的方式组合起来完成;而后者更强调翻译这项工作。

这也让我想起,前段时间和朋友聊起,我们这行未来能做什么。我并没有想好这个问题,但是会让我想到如果要转行,什么能力是通用的?在我看来其中一个就是解决问题的思路。小的问题比如家里一颗灯泡坏了怎么修?大的问题类似如果要设计一套银行系统需要怎么完成(我现在自然还不能胜任这项工作)?

也正是因此,前段时间教两个朋友编程的时候,我并没有怎么注重语法,而是更关注解决问题的思路。通过自然语言把问题拆解出步骤,然后翻译成代码。回想起当年自己自学的时候那种无力感实在痛苦,已经忘记是怎么熬过来的了。幸运的是,现在的人不必如此。

前段时间去了趟大英博物馆,看到了镇馆之宝罗塞塔石碑。两百多年前,法国人商博良 (Jean-François Champollion) 以这块石碑为突破口,破译了古埃及圣书体,成为埃及学创始人。这块石碑上印有三种文字,分别是古埃及圣书体、世俗体及古希腊文。或许在未来,非自然语言的代码都会被人遗忘。而某一段写着自然语言注释的代码会成为新的罗塞塔石碑。