Racket 宏定义给定重复模式的函数 [英] Racket macro to define functions given a repeated pattern

查看:39
本文介绍了Racket 宏定义给定重复模式的函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这个问题很难解释,因为我需要收集我的想法,所以请耐心等待.出于说明目的,我已经能够将问题简化为一个最小的示例.这个例子对于这有什么用没有任何意义,但我离题了.假设我想扩展球拍语言来编写如下所示的内容:

The problem is quite difficult to explain because I need to collect my thoughts, so bear with me. I've been able to reduce the problem to a minimal example for illustrative purposes. The example will not make any sense as to what this would be useful for, but I digress. Say I want to extend the racket language to write things that look like this:

(define-something
  (['a] 'whatever)
  (['b 'c] 'whatever2))

方括号之间是一个或多个符号的序列,后面是一系列球拍表达式(whatever,对问题陈述不重要)

Between the square brackets is a sequence of one or more symbols, followed by a sequence of racket expressions (the whatever's, which are not important for the problem statement)

该示例将匹配一个看起来像这样的宏:

The example would match a macro that looks something like this:

(define-syntax (define-something stx)
  (syntax-case stx ()
    [(_  ([symb ...] body ...) ...)
     #'()]))

实际上在这里我们匹配 0 个或多个符号,但我们可以假设总是至少有一个.

Actually here we match 0 or more symbols, but we can assume there is always going to be at least one.

在宏的主体中,我想使用连接的符号作为标识符生成函数定义.因此,对于我们愚蠢的示例,宏将扩展为:

In the macro's body I want to generate function definitions using the concatenated symbols as the identifier. So for our silly example the macro would expand to something like:

(define (a) 'whatever)
(define (bc) 'whatever2)

我发现了一个类似的问题,其中海报使用预定义的字符串列表生成函数,但我对宏不是那么流利,所以我无法翻译概念来解决我的问题.我想也许我可以尝试生成一个类似的列表(通过连接符号)并应用它们的策略,但我一直对宏定义中的所有省略号感到困惑.我也对他们在 with-syntax 中使用省略号感到有些困惑.

I have found a similar question where the poster generates functions using a pre-defined list of strings, but I am not that fluent with macro's so I have not been able to translate the concepts to solve my problem. I thought perhaps I could try generating a similar list (by concatenating the symbols) and applying their tactic, but I've been getting way too confused with all the ellipses in my macro definition. I'm also a bit confused about their use of an ellipsis in with-syntax.

推荐答案

使用 with-syntaxsyntax-case 可以解决这个问题,但最简单的方法是这是通过使用 syntax-parse 的语法类来实现的.通过定义解析符号列表并生成单个连接标识符的语法类,您可以将符号解析从宏体中提取出来:

It’s possible to solve this with with-syntax and syntax-case, but the easiest way to do this is by using syntax-parse’s syntax classes. By defining a syntax class that parses a list of symbols and produces a single concatenated identifier, you can lift the symbol parsing out of the macro body:

(require (for-syntax syntax/parse
                     racket/string))

(begin-for-syntax
  (define-syntax-class sym-list
    #:attributes [concatenated-id]
    (pattern (~and stx (sym:id ...))
             #:attr concatenated-id
             (let* ([syms (syntax->datum #'(sym ...))]
                    [strs (map symbol->string syms)]
                    [str (string-append* strs)]
                    [sym (string->symbol str)])
               (datum->syntax #'stx sym #'stx #'stx)))))

现在您可以非常轻松地定义宏:

Now you can define your macro pretty easily:

(define-syntax (define-something stx)
  (syntax-parse stx
    [(_ (syms:sym-list body ...) ...)
     #'(begin
         (define (syms.concatenated-id) body ...)
         ...)]))

请注意,这在 name 子句中使用了不带引号的符号,因此它的工作方式如下:

Note that this uses unquoted symbols in the name clause, so it would work like this:

(define-something
  ([a] 'whatever)
  ([b c] 'whatever2))

名称不能是计算为符号的表达式,因为需要在编译时知道信息才能用于宏扩展.由于您在评论中提到这是针对类似 FRP 的系统,因此您的信号图需要是静态的,例如 Elm 的.如果您想要构建动态信号图的能力,您将需要比宏更复杂的策略,因为该信息需要在运行时解析.

The names can’t be expressions that evaluate to symbols because the information needs to be known at compile-time to be available to macro expansion. Since you mentioned in a comment that this is for an FRP-like system, your signal graph will need to be static, like Elm’s is for example. If you want the ability to construct a dynamic signal graph, you’ll need a more complex strategy than macros since that information will need to be resolved at runtime.

这篇关于Racket 宏定义给定重复模式的函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆