我正在使用类似于 unix 的管道来研究球拍的语法,如下所示:
> ("FOO" > string-replace "O" "E" > string-append "x" > string-downcase)
"feex"
这是一个蛮力解决方案,它支持具有 2、1 和 0(额外)参数的过程:
(require (prefix-in racket/base/ racket/base) syntax/parse/define)
(define-syntax-parser #%app
[(_ data (~literal >) proc a b (~literal >) rest ...) #'(#%app (proc data a b) > rest ...)]
[(_ data (~literal >) proc a (~literal >) rest ...) #'(#%app (proc data a) > rest ...)]
[(_ data (~literal >) proc (~literal >) rest ...) #'(#%app (proc data) > rest ...)]
[(_ data (~literal >) proc rest ...) #'(#%app proc data rest ...)]
[(_ rest ...) #'(racket/base/#%app rest ...)])
问题是找到下一个管道,因为语法模式不允许多个 ... 模式。宏需要知道下一个管道在哪里关闭第一个管道的表单。除非有办法用不匹配的括号构建部分语法对象?
我可以嵌套椭圆,但是我必须使用额外的括号:
(define-syntax-parser #%app
[(_ data (~literal >) (proc params ...) > rest ...) #'(#%app (proc data params ...) > rest ...)]
[(_ data (~literal >) proc rest ...) #'(#%app proc data rest ...)]
[(_ rest ...) #'(racket/base/#%app rest ...)])
> ("FOO" > (string-replace "O" "E") > (string-append "x") > string-downcase)
"feex"
没有额外的括号有没有办法做到这一点?
我知道 clojure 的线程宏,但如果你必须嵌套它们,它们就很难遵循。