惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Y
Y Combinator Blog
V
V2EX
Jina AI
Jina AI
爱范儿
爱范儿
M
MIT News - Artificial intelligence
量子位
L
LangChain Blog
Google DeepMind News
Google DeepMind News
酷 壳 – CoolShell
酷 壳 – CoolShell
罗磊的独立博客
腾讯CDC
MongoDB | Blog
MongoDB | Blog
P
Proofpoint News Feed
宝玉的分享
宝玉的分享
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Last Week in AI
Last Week in AI
H
Hackread – Cybersecurity News, Data Breaches, AI and More
F
Fortinet All Blogs
The GitHub Blog
The GitHub Blog
Engineering at Meta
Engineering at Meta
博客园 - 聂微东
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
Vercel News
Vercel News
T
The Blog of Author Tim Ferriss

極客死亡計劃

Coffee Break Clojure, Vol.0 可怖的沉默 大脑充血 Vol.98 第一个人 Token 应译作「符」 大脑充血 Vol.97 少年承载了太多年长者的恶臭投射 现象学导论 Writing following the F-pattern is a horrible horrible idea Generated work should not be published. 大脑充血 Vol.96 给我发邮件吧,放轻松 计算机网络如何帮我理解「人们难以相互理解」? 大脑充血 Vol.95 骷髅编程 诺兰的《奥德赛》采取了什么样的改编策略? III 诺兰的《奥德赛》采取了什么样的改编策略? II 大脑充血 Vol.94 我的世界一直下雨 诺兰的《奥德赛》采取了什么样的改编策略? 大脑充血 Vol.93 新知识分子的新庸俗 艾尔特拉克在岣琅 大脑充血 Vol.92 川渝人在山东吃到没有辣味的麻辣香锅和红油水饺之后产生的哲学思考 Are We Interfacing Yet? 大脑充血 Vol.91 如何用宝可梦属性玩剪刀石头布? 什么是工程问题? 大脑充血 Vol.90
稻草人周刊 Vol.82
Eltrac · 2026-05-25 · via 極客死亡計劃

这周我把堆积在书签里没读的文章翻出来读了,发现其中有不少已经是两三个月前发布的内容了,他们跟随着一次次书签管理器迁移漂泊了好久,终于在周刊里找到了归宿。


I Hate It Here music cover

I Hate It Here

Taylor Swift

I’m lonely, but I’m good

I’m bitter, but I swear I’m fine

I’ll save all my romanticism for my inner life and I’ll get lost on purpose

This place made me feel worthless

Lucid dreams like electricity, the current flies through me

And in my fantasies, I rise above it

And way up there, I actually love it


我抛弃孩子,爱上妈妈,被全欧洲封杀,但我是个好人

📻

八卦不仅仅是娱乐方式,甚至是刻在人类基因里的生存本能,原始部落里有关哪个地方有猎物、哪里有野兽的信息就是通过类似八卦的方式口口相传的。得到更多的信息就意味着更高的生存几率。这么说来,八卦不仅不坏,甚至是有益于生存的、顺应天性的活动啊。

我跑题了。总之,偶尔读一读已故名人的八卦很有趣。

卢梭的《忏悔录》非常暴露地描写了自己人格中各种阴暗的部分,比如在贵族小姐面前露鸟、在见人之前为了不性欲大发所以在林子里自慰、把自己的第一次性行为献给了养母(以及他真的爱过她)…… 他和一些同时期的名人的关系也很有意思,会因为各种事情跟朋友写绝交信,临死前他的床榻旁已经没有什么人了,因为朋友都被他自己推走了。

我感觉,我在听一个一生都没有经历完整社会化的人的故事,想必童年失去父母的经历对他人格的影响真的很大,而他自己显然没有解决这些问题的意识(我严重怀疑卢梭甚至引以为豪,因为他在大庭广众之下数次朗读自己的《忏悔录》……)。不过,无可指摘的是,他的确创作了很多伟大的作品,而且从不生产烂作。

所以,我自己的童年也不算幸福(尽管也远不如他的悲惨),希望我不要变成卢梭那样的人。

看好你的硬件

📜

“AI”的算力需求越来越多,包括 RAM、SSD 和芯片在内的各种硬件资源全都流向了企业建造的数据中心。由于供不应求,硬件的价格越来越高,作者预言这次短缺并不是临时的,不像以往的加密货币挖矿潮和其他的临时短缺,如今的硬件价格高昂可能是常态,所以要做好没办法随时用可支付的价格更换硬件的准备。

对硬件制造商来说,企业端的需求更大,给的钱也更多,而消费者端不仅给的钱少,要求也多,不好满足,如此看来,制造商优先满足企业需求是必然的,给消费者的硬件产品只会越来越少,甚至越来越贵。作者还预言,既然已经有企业提供租用电脑服务了,如果这种趋势一直发展下去,那么我们可能会迎来大部分人都不拥硬件、不拥有算力的时代,大家都只持有一台连接到云计算机的终端,缴纳订阅费使用此类服务。联想到已有的各种 SaaS 和流媒体服务,硬件即服务的未来似乎也不那么像是杞人忧天了。

这也导致算力和权力结构的中心化。当然,如果依照 Volpe 的预言 ,“AI”泡沫必将破裂的话,“AI”公司建立的数据中心终将闲置,人们将有办法购买或租赁到非常便宜的云服务器。

就算不相信这样的未来即将到来,「Buy it for life」的思想也是值得学习的。即便消费者文化持续,也不代表所有人都要参与到这种文化当中。

框架的假象

📜

所以 Planet Clojure 为什么会把一篇十年前的文章推送到 Feed 里?

这篇文章先描述了这种困境:如果你使用框架编写 Web 应用,一开始可能会感到非常顺手,CRUD 以及各种基本操作非常省心,但投入很多时间精力过后,可能会发现框架的部分功能并不称心如意,这个时候提交问题可能并不会得到结果(比如开发者认为这不在框架的问题范围之内),这个时候你的选择要么是抛弃这个框架重写,要么是 Fork 这个框架自己添加想要的功能,但都很耗时耗力。

然后作者介绍了 Luminus ,一个轻量级的 Clojure Web 框架。这个框架的特点是,它需要你自己做很多决策,比如用什么数据库,引入什么第三方库,此外,脚手架一旦搭好,Luminus 的未来更新完全不会影响你的代码,除非你主动选择。

看起来不错,但我想,使用任何一种框架,最核心的业务逻辑都应该是高度抽象的,不应该依赖底层细节,而框架提供的 CRUD 等能力明显是底层细节。如果开发者被框架困住,我想他需要审视一下自己的架构决策,让业务逻辑直接依赖框架是非常糟糕的。迁移框架当然要费不少精力,但绝非「必须重写」那么巨大。

举个例子:

Framework <- Middle Man -> Service <– ServiceImpl

如果 ServiceImpl 让你想起 Java 开发,请见谅,这的确是更好的设计

上述箭头描述的是依赖关系,空心箭头表示实现接口。简单来说,有一个中间人(Middle Man)了解如何调用框架和包含业务逻辑的服务类,这样业务逻辑就不需要直接依赖框架了。如果后续需要更换框架,只需要重写中间人,业务逻辑无需修改。

同时要注意 Service 是高度抽象的,不依赖任何其他组件,如果需要调用别的具体实现,应该写在 ServiceImpl 实现类里,这样就保证了业务逻辑足够抽象,不依赖不应该依赖的东西(接口隔离原则),也保证业务逻辑不需要经常修改,有需求变动时只需要拓展或更换实现类(开闭原则)。

用 Lua 写 HTML 模板可能很酷

📜

作者先对比了 Handlebars 和 Go 的 html/template 库,两者是相似的 HTML 模板引擎,都允许用户在 HTML 模板里用类似 {{ }} 的语法插值,编写简单的赋值语句、循环结构和条件结构等等。不过 Go 的库要比前者(Rust 实现)更小巧,功能也差不多,在某些设计上也更讨喜(比如 Handlebars 有可怖的三括号语法 {{{ }}}Lisp 程序员看了都摇头)。

后来作者发现了 Maud (Rust 的宏),可以用这种格式写 HTML:

html! {
    h1 { "Hello, world!" }
    p.intro {
        "This is an example of the "
        a href="https://github.com/lambda-fairy/maud" { "Maud" }
        " template language."
    }
}

看起来简洁得多,但实现很复杂,这个宏有 3000 行左右的代码,作者不喜欢。而 Lua 这边能使用十分简洁的原生语法,实现类似的效果,这归功于 Lua 优雅的语法设计,在函数只有一个参数时可以省略括号(比如 print("a") 可以写成 print "a"),如果这一个参数是数组或映射(Lua 的 table),就可以在不写圆括号的情况下,用花括号写入数组或映射的值。

如果用 Lua 的函数作为 HTML 标签的表示,就可以得到如下的结构。

h.Document{
	lang = "en",

	h.head{
		h.meta{charset = "UTF-8"},
		h.title{"Hello, world!"},
	},

	h.body{
		h.h1{"Hello, world!"},
		h.p{
			"This is an example of the little HTML templating framework I wrote ",
			"in Lua in like 20 minutes."
		},
		h.p{
			"As you can see, it is fully capable of generating any kind of markup ",
			"you'd ever want.", h.br(),
			"It can even do things like ", h.b"bold text", "!"
		},
		h.p"This is some embedded HTML <p></p>"
		h.img{
			alt = "riki sitting in pink space",
			src = "https://riki.house/static/character/riki/sitting.png",
			width = 2223, height = 1796,
			style = "width: 20%; height: auto;"
		},
	},
}

另一个好处在于,由于是直接用一门编程语言写的模板,只要利用语言本身的变量、字符串拼接、循环和分支结构,就不需要实现类似 {{ }} 的语法了。据我所知,Lua 本身也十分小巧,很容易嵌入其他语言编写的程序当中,就算不用 Lua 写博客程序,也可以专门嵌入在程序里做模板引擎。

好了,写到这里我终于憋不住了:Lisp can be the coolest HTML templating engine!

[:html 
  [:head
    [:title "Eltrac"]
    [:meta {:charset "utf-8"}]
    [:meta {:name "viewport" :content "width=device-width,initial-scale=1"}]]
  [:body
    [:main.i-am-a-class#id 
      [:p "Be cool. Use Clojure."]]]]

上面是 Clojure 的 Hiccup 库,不少其他的 Lisp 方言也有类似的库,因为用 S-expression 编写 HTML 非常自然且简洁。 Spineret (Common Lisp 库)的写法与 Hiccup 类似,但只有圆括号:

(defmacro with-page ((&key title) &body body)
  `(with-html
     (:doctype)
     (:html
       (:head
        (:title ,title))
       (:body ,@body))))

(defun shopping-list ()
  (with-page (:title "Home page")
    (:header
     (:h1 "Home page"))
    (:section
     ("~A, here is *your* shopping list: " *user-name*)
     (:ol (dolist (item *shopping-list*)
            (:li (1+ (random 10)) item))))
    (:footer ("Last login: ~A" *last-login*))))

你看到那几个优雅得要命的宏了吗?

Lisp 设计模式

📜

可能是我对设计模式这个概念的理解有偏差(也可能是因为软件领域的用词向来很混乱……),我总觉得这篇文章更像是在介绍如何利用语言特性,而不是在讲设计模式,或者仅仅是编程模式(Programming Patterns)而非设计模式(Design Patterns)。

首先是允许后端成为软件的插件(也就是随时更换具体实现)的 Protocols(协议)和 Monkey Patching(猴子补丁)。Common Lisp 和 Clojure 都支持 Protocol(defgenericdefprotocol),这和 OOP 语言的 Interface 差不多,可以把面向接口编程的经验复用到一些 Lisp 中。至于 Monkey Patching,是指一些语言允许用户改写已有的函数,比如 Emacs Lisp 的 Adivces 和 Common Lisp 的 :around 方法,也就允许用户自己编写并替换软件的部分实现。

然后是 Hooks(钩子),这就更接近设计模式了,把函数存放在一个列表(或别的什么数据结构里),当有事件发生时,就调用这里面的函数。我想起某本 Java 设计模式里也有类似的案例,叫作观察者模式(Oberver Pattern)或监听者模式,被监听对象储存一系列监听者的引用,当事件发生时,由监听对象调用监听者的方法。不过在函数式编程中,我们直接储存函数本身,不和对象打交道。

其次是 Fail Fast, Fail Often(快错常错),这更像是开发模式。简而言之,作者表示他在非 Lisp 语言里很害怕看到报错,但在 Lisp 里就不会,因为以 Common Lisp 为首的部分 Lisp 方言有类似的语言特性,可以快速在报错之后快速重启程序,如果遇到暂时不想处理的错误,可以直接忽略,还能使用 use-value 这样的特性临时替换有问题的参数。在 Common Lisp 以外的方言,程序员也可以使用 REPL(可以理解为直接与代码库交互的命令行程序)调试程序,在 REPL 里也可以重新定义函数和变量,重新运行程序,非常方便。

再者是 Dynamic Variables(动态变量),看起来很吓人的一个模式,因为它似乎违背了函数式编程范式,给变量赋值了。这是作者给的示例代码:

(defmethod gimage:apropos* :around (string &optional package external-only docs-too)
  (let ((*print-case* :downcase)
        (*print-level* 2)
        (*print-lines* 2)
        (*print-length* 10))
    (call-next-method)))

我不懂 Common Lisp,但我熟悉 let,这个函数(也可能是宏或者保留字,我不清楚底层是怎么实现的)的第一个参数是是个储存二元关系1的列表,用于声明绑定(Bindings),余下的参数都是待求值的表达式。这里确实是给变量赋值了,但仅限于 let 块内,是在限定作用域内改变状态以修改行为的做法。无论怎么说,我还是觉得这不太优雅,为什么一定要用绑定,不能给函数传递参数呢?

[1]

死去的离散数学突然开始攻击我…… 这里说的二元关系就是只储存了两个元素的列表,实际上是键值对。 ↩︎

最后是 Destructuring(解构),这其实是语言特性,它的作用是把复杂的数据结构分解为扁平的、易用的结构,比如把键值对映射解构为几个简单的变量。作者给的 Guile/Scheme 例子有太多我不熟悉的函数,所以我写个 Clojure 的例子。

(defn http-request [url & {:keys [Accpet Cookie Content-Type]
                           :or {} ;; 默认值
                           :as opts}]
  ;; 直接使用 Accept、Cookie 和 Content-Type
  ;; 也可以用 opts,结构是 {:Accept ... :Cookie ... :Content-Type ...}
  )

(http-request "https://example.com" :Cookie {"key" "value"})

这在构造有很多可选参数的函数时非常有用。如果用户传入的参数本身就是个映射,则可以用 let 解构。

(defn http-response [response]
  (let [{:keys [status headers body]} response]
    ;; 直接使用 response map 里的 status、headers 和 body
  ))

不过这也不是 Lisp 专属的,因为 JavaScript 也可以解构。

const { status, headers, body } = response

[a, b, ...rest] = [10, 20, 30, 40, 50];
console.log(rest);
// Expected output: Array [30, 40, 50]

印象中 Python 也可以,作者甚至把解构称作「Pythonique」。


Jant

Owen 开发的博客程序,兼具动态博客的便利和静态博客在长期保存方面的优势,很有趣的设计。

所以其实我的痛点是我想既要又要,既想发布方便,又想保有某种长期格式。我给 Jant 设计了自动同步的 GitHub Sync 解决了这个问题。Jant 博客可以生成一个完整的 Hugo 站点,每次在 Jant 发帖都会自动同步到 Github Repo,这里是一个示例 Repo。它既是备份,也是一份完整的,可以独立运行的静态博客。

不过要是能用 Git 同步到任意远程仓库就好了,实在不想用 GitHub。

访问: Jant


  • 自我暴露不只会引来有相同感受的人的亲近感,产生有意义的交流,还有可能引来平庸者站着说话不腰疼的评价,说的是我听过也想过而且和我想表达的东西毫不相关的陈词滥调,想半天还是不理对方比较好。

  • 某天和朋友玩星露谷物语,一边钓鱼一边闲聊,聊起《存在主义咖啡馆》这本书。我半开玩笑说加缪就是那本书里讨论的哲学家里最帅的一个,说着就从我书房里找到了四张加缪的照片,然后…… 然后我就意识到自己好像有点变态,不敢去找那第五和第六张了。

    但是加缪真的太帅了,法兰西顶流帅哥

    朋友:希望你只是把他当作你的精神导师。