racket - 如何匹配球拍中的语法?
问题描述
我想编写一个与给定语法是否匹配的宏 a if
or cond
,我尝试像这样编写它:
(define-syntax (foo stx)
(syntax-case stx ()
[(_ (if a b)) #'"if!"]
[(_ (cond a b) #'"cond!"]))
但它总是匹配第一种情况。如何区分这两种情况?
解决方案
在syntax-case
模式中,标识符匹配任何内容。您已经假设这是真的:当您编写模式时(if a b)
,大概您假设a
将匹配任何语法,而不仅仅是文字标识符a
。标识符也是如此if
——您实际上并没有检查标识符是否为if
,您只是匹配任何语法并将其绑定到名为 的模式变量if
。
这就是文字列表的用途。当您将标识符放在文字列表中时,它会告诉syntax-case
您检查该特定标识符而不是绑定模式变量。所以你可能想要这个,而不是:
(define-syntax (foo stx)
(syntax-case stx (if cond)
[(_ (if a b)) #'"if!"]
[(_ (cond a b) #'"cond!"]))
但是,请注意,它syntax-case
已经很老了,而且 Racket 已经提供了一个更好的语法匹配库近十年了,syntax/parse
. 我会syntax-case
在所有情况下都推荐它。上述宏的syntax/parse
等效项如下所示:
(require (for-syntax syntax/parse))
(define-syntax (foo stx)
(syntax-parse stx
#:literals [if cond]
[(_ (if a b)) #'"if!"]
[(_ (cond a b) #'"cond!"]))
……基本一样,但是syntax-parse
的模式语言比 . 丰富得多syntax-case
。例如,如果您想省略#:literals
声明,您可以使用以下方法注释各个文字模式~literal
:
(define-syntax (foo stx)
(syntax-parse stx
[(_ ((~literal if) a b)) #'"if!"]
[(_ ((~literal cond) a b) #'"cond!"]))
有关详细信息,请参阅syntax/parse
.
推荐阅读
- python - 在 Node-RED 中使用 Python 节点而不暴露代码
- javascript - 在shopify中向product-card-grid.liquid写入函数时,Javascript简单函数未执行?
- ruby-on-rails - 如何使用 exec_params where params in ('','','')
- c# - 表单帖子字段之一返回 NULL .NET Core MVC
- java - mybatis中如何将String[]映射到PostgreSQL数组列
- reactjs - SyntaxError: Unexpected token < at ScriptTransformer._transformAndBuildScript (../../node_modules/jest-runtime/build/script_transformer.js
- .net-core - .NET 5 未编译为单个文件可执行文件
- java - 避免 @Secured 注解的重复值
- multithreading - 添加回调而不是使用默认实现
- css - 是否可以在 RadioGroup 中使用常规按钮作为单选按钮?