diff options
| author | eltrac <hi@eltr.ac> | 2026-04-03 16:08:52 +0800 |
|---|---|---|
| committer | eltrac <hi@eltr.ac> | 2026-04-03 16:08:52 +0800 |
| commit | 9fcd9e411183cc4d7642301bd6bbeb23e8227d82 (patch) | |
| tree | 0254feed1d0872242ac9c39d12580578402dec2f /content | |
| parent | fc4ea2b8b95d847932b9e1d4c113f58a7e1b5d97 (diff) | |
docs: new weekly draft
Diffstat (limited to 'content')
| -rw-r--r-- | content/weekly/75.md | 121 |
1 files changed, 121 insertions, 0 deletions
diff --git a/content/weekly/75.md b/content/weekly/75.md new file mode 100644 index 00000000..cb3b0552 --- /dev/null +++ b/content/weekly/75.md @@ -0,0 +1,121 @@ ++++ +title = "稻草人周刊 Vol." +subtitle = "" +tags = ["Lisp"] +date = 2026-04-02T23:52:12+08:00 +draft = true +toc = true ++++ + +{{< music cover="" title="" artist="" apple="" spotify="" netease="" >}} + +<!--more--> + +## 连接 + +### 控制你的标记语言 + +> [!note] 📜 +> [控制你的标记语言 - 空栈顶](https://emptystack.top/control-your-markup-language/) + +作者介绍了几种 Markdown 和 Org Mode 以外的用于写作的标记语言,其中 Lisp 含量达到了~~惊人的~~ 80%。 + +和我之前写过的《[网页即列表!](/posts/webpage-as-lists/)》的思想类似,既然要把标记语言编写的文本转化为 HTML,而 HTML 构成的嵌套的 DOM 树本身就是树形结构,那么用 S-expression(Lisp 语言所采用的表达式,即列表或者说括号的嵌套)编写网页就非常合理,并且比用 XML 或 HTML 干净不少。 + +首先是 [Pollen](https://docs.racket-lang.org/pollen/index.html),据说是 Matthew Butterick 用 WordPress 写在线书时嫌弃它不够灵活,所以开发了 Pollen。这个标记语言把一篇文章(或者一本书)都当作 X-expression(用来表示 XML 数据的 S-Expression,常在 Racket 这门 Lisp 方言里使用),为了让更多人使用它,它还兼容 Markdown。*为什么这么多新标记语言都在兼容 Markdown,是因为用的人实在太多了吗?* + +如果这么写: + +```pollen +#lang pollen + +Deep Thought +============ + +I am **so** happy to be writing this. +``` + +就会被 Pollen 解析为: + +```racket +'(root + (h1 ((id "deep-thought")) "Deep Thought") + (p "I am " (strong "so") " happy to be writing this.")) +``` + +最后被转化为 HTML: + +```html +<root> + <h1 id="deep-thought">Deep Thought</h1> + <p>I am <strong>so</strong> happy to be writing this.</p> +</root> +``` + +Pollen 的灵活性体现在自定义标签(custom tagst),比如图片写作 `◊image["图片地址"]{图片描述}` 而链接写作 `◊link["链接地址"]{链接文本}`(*Org Mode 正在攻击我,混杂着 Markdown 和奇怪的东西*),`image` 和 `link` 可以换成自己定义的函数。 + +可以用类似的方式定义如何把某个标签转换为 X-expression: + +```racket +(define (image url alt) + `(img ([alt ,alt] [src ,url]))) +``` + +之后就可以把 X-expression 转化为 HTML,或者 PDF 等任何标记语言。在我看来,Pollen 有点像是 [Pandoc](https://pandoc.org/),可以自己编写某个语言的 Reader 和 Writer,前者用于把源语言转换为 AST(抽象语法树),后者把 AST 转换为目标语言,不过对 Pollen 而言,Lisp(X-expression)充当了 AST 的作用。 + +另外 Pollen 可以一边定义语法一边写文,说实话,看起来很爽。 + +```pollen +#lang pollen +◊(define ($ . xs) + `(mathjax ,(apply string-append `("$" ,@xs "$")))) +◊(define ($$ . xs) + `(mathjax ,(apply string-append `("$$" ,@xs "$$")))) + +◊h1{I wonder if ◊${2^{\aleph_\alpha} = \aleph_{\alpha+1}}?} +``` + +这篇文章还介绍了 Alain Marty 的 Lambda Talk,不过引用的两个链接都需要 JavaScript 才能加载内容,我拒绝为了读文档而加载 JavaScript,加上这个标记语言看起来也没有特别吸引我的地方,所以就没有去了解了。作者还提出用 Tcl 这门不需要括号和引号的**编程**语言来写文档,也是有趣的实践,而且编程语言无疑要比标记语言灵活得多。 + +作者还讨论了在 Markdown 里插入代码的方法(不是代码块),首先排除了 MDX(本质上是 Markdown 加上 JSX 这个邪恶的东西),需要 Node.js 才能运行;又排除了 Org Mode,原因如下: + +> Org-mode 相对 markdown 有更多的功能以及根植于 Emacs 的可扩展性。然而正是因为 Org-mode 功能太丰富我才选择扩展 Markdown——扩展的平台必须足够简单,才能让扩展完的成果保持简单。 +> +> 当然,Org-mode 只有在 Emacs 中才能获得良好体验也是我选择 Markdown 的原因之一。 + +作者目前的解决方案是使用 Pandoc filter,这其实就是在对 Pandoc Reader 解析得到的 AST 做处理,比如把标记为 `mermaid` 的代码块转换为 SVG 代码再由 Pandoc Writer 输出为指定格式。我由于使用 Hugo 写博客,所以短代码(shortcode)在大多数时候就够用了,不过体验上是没有 Pollen 一边造语法一边写文的体验爽的,也没有 Pandoc 那样的兼容性。 + +很有意思的文章,说不定哪天我真的开始用 Lisp 写文章了呢。 + +### 用 Vim 写 Lisp + +> [!note] 📜 +> [Lisp in Vim](https://susam.net/lisp-in-vim.html) + +书接上文,前面说到 Org-Mode 只有在 Emacs 中才能获得良好体验,而 Lisp 也非常适配 Emacs,毕竟这个编辑器的核心就是一个 Emacs Lisp 解释器(或者说 REPL?)。不过,我非常固执,始终不太愿意选择 Emacs(兴许会用 Emacs 写文或者记笔记,但写代码我还是更喜欢 (Neo)vim),幸好 Vim 也可以通过插件和配置得到很好的 Lisp 编辑体验。 + +要获得良好的 Lisp 编程体验,需要两个工具: + +1. 用于编辑 S-expression 的结构化编辑功能(否则就真的 *Lost In Stupid Parentheses* 了) +2. 内嵌 REPL[^1] 以实现交互式编程(否则和非 Lisp 语言还有什么区别) + +作者在文章介绍了如何使用 Vlime(类似于 Emacs 的 SLIME,用于交互式编程)和 Paredit(括号编辑,或者说结构化编辑)。前者本质上是启动了一个服务器,这个服务器运行 REPL,接收来自编辑器的表达式,计算表达式后返回值给编辑器。比如,在 Vim 里选中 `(+ 1 2)`,执行 Eval 操作,Vlime 就会把这个字符串发送给 REPL 服务器,然后得到返回值 `3` 显示出来。 + +这有点像 LSP(语言服务器协议),编辑器把代码发送给语言服务器,然后把语言服务器分析得到的警告、报错和优化建议显示给用户。不过 REPL 要更强大,不仅仅是计算。比如,如果把一个函数定义发送给 REPL,它就会记住它,在同一个会话下,可以在之后的 Eval 操作里直接使用这个函数。这就是交互式编程,可以直接对 S-expression 求值,不需要手写 `print` 或者 `console.log` 之类的。 + +不过 Vlime 有点老了,而且是给 Vim 写的。对于 Neovim 用户,可以选择用 Fennel(用来写 Lua 的 Lisp 方言)实现的 [Conjure](https://github.com/Olical/conjure),这个插件甚至还能实现 Lua、Python 和 SQL 等语言的交互式编程。 + +至于 Paredit,我的选择是 [nvim-paredit](https://github.com/julienvincent/nvim-paredit) 插件,Paredit 的实现大概都没有太多区别。 + +### + +> [!note] 📃 +> [Why free stuff makes us irrational](https://thehustle.co/why-free-stuff-makes-us-irrational) + +## 星群 + +## 切片 + + +[^1]: REPL:Read-Eval-Print-Loop,输入-计算-打印-循环。 + |
