Calcit 相比 Clojure 一些有意思的元编程能力 #226
tiye
started this conversation in
Show and tell
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
Cirru Edn 里写代码
Calcit 使用的数据格式 Cirru EDN, 本身用了 Cirru 的语法做标记,
于是代码的语法是基于 Cirru 的, 数据的格式也是基于 Cirru 的,
结果, 我可以直接把 Calcit 代码通过一个
quote
的指令直接放在数据当中, 写法比如:其中
%{}
是一个类似 HashMap 的结构, 其中包含了一段代码.这段代码来自 Calcit 的源码, 可以把程序的定义都放在这样的数据结构当中:
https://github.com/calcit-lang/calcit/blob/main/src/cirru/calcit-core.cirru#L1108-L1113
这为 Calcit 提供了不小的便利, 比如 Calcit 的 API 文档, 完全就是这样写的:
https://github.com/calcit-lang/calcit-apis/blob/main/docs/apis.cirru#L8-L10
格式化表达式
Calcit 的宏大致模仿的 Clojure, 相对较弱, 不过因为用的 Cirru 语法, 格式化非常方便,
比如这个例子当中我要查看代码结构, 可以通过
format-to-cirru
输出带缩进的格式化结果:模拟 Sum Types
由于在动态语言里缺少类似 Rust enum 类似结构来模拟 sum types, 我在 Calcit 尝试类似的方式模拟,
比如用 List 来模拟, 然后第一个元素标记作为 tag 的方式来用, 然后配合 pattern matching 语法,
后来再基于之前从 Rust 模拟的 Tuple 结构再做简化, 形成了现在的语法:
其中
::
用于定义 Tuple 结构,:complex
是一个 Tag, 对应 Clojure 里的 keyword.同时这个结构也提供一部分面向对象的写法的能力,
其中
%::
相比::
可以额外在设置一个 prototype 的结构, 这里不展开,但这样设定以后,
.add data
可以用类似面向对象的方式调用.(尽管整体是不可变数据, 也不会有继承)当然这个功能来说, Clojure 是有很多多态手段的, 整体是更强大的.
展开符号内部信息
&extract-code-into-edn
将一个 symbol 一些内部信息展开, 比如得到 symbol 得命名空间和所在函数定义的信息.获取命名空间在 Clojure 当中应该是有的, 而获取所在定义应该是 Calcit 独有(来自 Cirru 结构设计),
这个功能本身不算复杂, 配合 Macro 能提供比较有意思的功能, 比如 Respo 定义的 CSS in Calcit 写法
实际使用时就可以通过 defmacro 获取到
style-a
的命名空间(比如说app.main
), 和符号内容,于是就可以生成一个应用级别的
style-a__app-main
这样一个字符串, 作为className
使用.这个对应 emotion css 的场景, emotion 会生成
css-1223d3
这样带着 HASH 的名字,要进一步加上 Babel 编译, 能带上原始的命名. 这个在支持 Macro 的语言当中就很容易了.
再配合定义的位置, 就可以定义出来一个全局唯一的名字, 比如
<namespace>_<def>_<local>
这样,这个字符串可以作为一个全局的 key 使用, 关联到一个全局状态上.. 从而模拟一个局部状态.
之所以我觉得这样有意思, 是因为这个场景有点类似
useState
这类局部状态的能力,(尽管看看效果, 还是感觉不够简短, 但也算提供了一种并不繁琐的思路)
数据转回代码
&data-to-code
有意思的地方是把数据转回代码:这个是方便生成 JavaScript 用的. 实际当中场景是从文本的配置中读数据, 生成 JavaScript 代码再重新执行得到数据.
这个可以提供一些便利, 把配置数据从 Calcit 程序当中分离出来, 同时避免再浏览器端重新做文本解析.
Beta Was this translation helpful? Give feedback.
All reactions