文章摘要
文章探讨了在Emacs中扩展使用Fennel的可能性,指出虽然Guile Emacs支持多种语言,但由于兼容性问题,直接使用Lua可能更为实际。尽管已有尝试将Lua VM集成到Emacs中,但稳定性尚不足。作者建议通过外部连接的方式实现Emacs与Fennel的交互,以充分利用Lua的简洁性和灵活性。
文章总结
使用Fennel扩展Emacs
在今年的EmacsConf上,看到Guile Emacs被重新提起后,我开始思考:为什么我们只能局限于Guile?虽然Guile不仅仅是一个Scheme实现,得益于其基于编译器塔的设计,Guile VM还支持其他语言,如Emacs Lisp、ECMAScript、Brainfuck、Lua、Ruby和Python。然而,Guile Lua并非PUC Lua,即使是LuaJIT也难以完全兼容现代Lua版本,导致我们停留在Lua 5.1和5.2之间,而PUC Lua已经发展到5.4。未来版本的差异可能会进一步扩大。
考虑到Lua的简单性,我决定直接使用Lua,而不是依赖Guile。虽然无法直接从Emacs Lisp运行Fennel函数,但Emacs可以连接到Fennel REPL,就像它支持Common Lisp或Clojure一样。尽管语言运行在单独的进程中,存在一些细微差别,但这仍然是一个可行的方案。
为此,我开发了一个小包:require-fennel.el。它能够加载Fennel(或Lua)模块,并为模块中的每个Fennel函数在Emacs端定义一组函数。
从Emacs Lisp运行Fennel
例如,我们可以这样加载Fennel:
emacs-lisp
(require-fennel fennel)
现在我们可以使用各种Fennel函数,例如fennel.eval:
emacs-lisp
(fennel.eval "(fcollect [i 1 10] (* i i))")
;; => [1 4 9 16 25 36 49 64 81 100]
或者,我们可以创建一个文件greet.fnl:
fennel
(fn greet [name]
"Greets NAME with a message."
(print (.. "Hello, " name " from Fennel!")))
并加载它:
```emacs-lisp (require-fennel greet)
(greet "Andrey") ```
Emacs会显示“Hello, Andrey from Fennel!”。
数据转换
在将数据从Emacs Lisp传递给Fennel时,转换表如下:
| Emacs Lisp | Fennel |
| --- | --- |
| [1 2 3] | [1 2 3] |
| (1 2 3) | [1 2 3] |
| ((:foo . 1) (:bar . 2)) | {:foo 1 :bar 2} |
| #s(hash-table test equal data ("foo" 1 "bar" 2)) | {:foo 1 :bar 2} |
| :foo | "foo" |
| 'false | false |
| "foo" | "foo" |
从Fennel接收数据时,转换表如下:
| Fennel | Emacs Lisp |
| --- | --- |
| [1 2 3] | [1 2 3] |
| {:foo 1 :bar 2} | ((:foo . 1) (:bar . 2)) |
| (values 1 2 3) | (1 2 3) |
| (fn []) | (lambda (&rest args) ...) |
| userdata | #<udata: 0x55b66bd6ac28> |
| true | t |
| nil, false | nil |
更多示例
我加载了许多自己编写的Fennel库,例如cljlib和JSON解析器。甚至可以将Fennel版本的Clojure库clj-http加载到Emacs中,并从Emacs Lisp调用它。
从Fennel调用Emacs Lisp
由于这个包使用了Fennel Proto REPL,我们可以创建一组函数,允许我们回调到Emacs Lisp。例如:
fennel
(emacs.call.emacs-uptime)
;; => "19 minutes, 17 seconds"
Fennelmacs
现在我们可以编写Fennel脚本,从Emacs获取数据,处理后再传回结果。虽然这与Guile Emacs不同,但它展示了Emacs的强大功能。如果你也喜欢Fennel,希望你能享受使用这个包的乐趣!
评论总结
总结:
关于Fennel的讨论:
- 正面评价:Fennel被推荐用于游戏开发,特别是与TIC-80、Love和PICO-8等游戏引擎的集成。评论者tmountain表示:“Fennel absolutely rocks for creating games.”(Fennel在游戏开发方面非常出色。)
- 疑问:部分用户对Fennel不了解,如psychoslave提问:“Sorry, but what is Fennel?”(抱歉,Fennel是什么?)
关于Emacs配置的讨论:
- 有趣的观点:adastra22提到可以用Brainfuck配置Emacs,并认为这是非常合适的:“TIL you can configure Emacs with Brainfuck. This is so appropriate.”(今天才知道可以用Brainfuck配置Emacs,这太合适了。)
关于Fennel与Emacs的关系:
- 误解:campak误以为Fennel是Emacs的扩展:“came thinking somehow fennel the seed extended Emacs”(我原以为Fennel是Emacs的某种扩展。)
总结中,Fennel在游戏开发中的优势得到了肯定,但也有用户对其不了解。Emacs配置的讨论则带有一定的趣味性,而关于Fennel与Emacs的关系存在误解。