编写 Racket 模块一些简单的记录

0

周末两天的时间写了用 Racket 运行 Cirru Sepal 的 prototype
https://github.com/Cirru/cirrusepal-rkt
https://github.com/Cirru/cirruparser-rkt
我有个毛病就是东西开开心心写的原型, 然后就丢着不管了.. 玩够了吧.
Sepal 项目目标是用 Cirru 语法去写其他语言的 IR 或者 AST 运行..
因为 Cirru 原来就是受 Lisp 元编程启发, 在 Lisp 当中能实现最有意思
而 Lisp 当中门槛文档最好而且门槛也不高的, 莫过 Racket.

我设计 Cirru 语法以前就学过点 Scheme, 但没写出来像样的程序
现在的话因为渐渐理解了 immutable 数据, 感觉不那么陌生了
再说我只是用 Racket 模仿 CoffeeScript 功能, 不会涉及复杂的功能
跟之前文章一样, 我要梳理下模块化跟打包方面的思路, 这个很不好记忆...
也只是零零岁岁记录一下, 万一用到能很快找到想起来

模块托管

Racket 0.6 经历一次大的升级, 之前用的 PLaneT 不再推荐, 只是兼容
我怀疑文件后缀从 .ss 变成 .rkt 也是这个时候改的
新的方案模块是说在 Web 或者本地 serve 就可以, 具体要研究下文档
让我关注的一个是, 代码可以托管在 GitHub 上, 用一个命令安装到本地:
http://docs.racket-lang.org/pkg/getting-started.html#%28part._github-d...

raco pkg install git://github.com/Cirru/parser-rkt

模块 collection 概念

这个概念有点像是 npm 当中的模块名, 但细节却奇怪, 反正又不对应模块名,
模块的名字好像直接就文件名了, 如果是从 GitHub 安装, 就是仓库名,
一般 Racket 中 require "dir/sub" 是引用相对路径的, 注意引号
require collection/file 没有引号, 是引用 collection 当中的文件
Racket 运行多个模块共用一个 collection, 但是文件又不能冲突, 很不理解
因为 collection 跟文件名分开的, 两者好像完全搭不上了

所有下载的文件都统一存放在系统某个目录比如:

➤➤ ls /usr/local/Cellar/plt-racket/6.1.1/share/racket/collects

总之引用模块, 引用文件, 两种需求可以写出来了
而模块的 collection 在根目录 info.rkt 里定义, 语法也不大确定
具体细节还是看文档上吧: http://docs.racket-lang.org/pkg/metadata.html

racket#lang info
(define collection "cirrusepal")

模块开发

开发模块的时候, 可能根据模块名字引用文件已经有需要了, 所以一般会做 link,
link 实际实际上就是在安装目录跑一个命令, 把开发中的模块安装到全局:

textraco pkg install

实际上就是在某个文件路记录了链接的信息而已:

text➤➤ raco pkg show
Installation-wide:
 Package       Checksum                                    Source
 racket-lib    436f0928598fc1a8abf27422e8e6588bef45f652    (catalog racket-lib)
User-specific for installation "6.1.1":
 Package       Checksum    Source
 parser-rkt    #f          (link ../../../../repo/cirru/parser-rkt)
 sepal-rkt     #f          (link ../../../../repo/cirru/sepal-rkt)
➤➤ cat ~/Library/Racket/6.1.1/share/info-cache.rktd
((#"../../../../repo/cirru/sepal-rkt" (collection version) (lib "cirrusepal") 1 0) (#"../../../../repo/cirru/parser-rkt" (collection version) (lib "cirruparser") 1 0))

模块 require provide 语法

文件之间, 模块之间, 怎样相互引用, 上面大概描述了一遍
然后是文件导出代码的方法... 用关键字标记就好了, 看文档:
http://docs.racket-lang.org/guide/module-basics.html
注意关键字是奇怪的 provide, 不是前端某个新加的关键字

然后顶部的 #lang racket 是特殊的语法, 是 module 的简写
具体看文档, 好像照着别人的用法直接写就算了...
http://docs.racket-lang.org/guide/Module_Syntax.html#%28part._hash-lan...

Racket 是有意思的语言, 但我估计不会深入挖, 需要时候查文档就算了, 很全的
http://learnxinyminutes.com/docs/racket/
http://docs.racket-lang.org/reference/index.html

关于 eval

另外关于 Sepal 核心的原理, eval 使用时要注意点东西, 看这个回答:
http://stackoverflow.com/a/22742799/883571

racket(define ns (make-base-namespace))
(define expr '(+ x 1))
(for/list ((x '(2 5 3 1 99 12)))
  (eval `(let ((x ,x)) ,expr) ns))
=> '(3 6 4 2 100 13)

我也只是零零碎碎记一点东西, 目前没时间没兴趣深入去学 Racket.


如果觉得我的文章对你有用,请随意赞赏

你可能感兴趣的

载入中...