【问题标题】:Ascending Numbers in Macro Definition宏定义中的升序数字
【发布时间】:2016-11-29 07:28:27
【问题描述】:

我经常使用 Racket 的模式匹配构造 match,并且我想了一种方法来帮助自己使用 match 调试程序并了解 Racket/Scheme 宏的工作原理,即创建一个包含信息的宏比如匹配了哪个模式。

换句话说,我希望创建一个宏,鉴于此:

(match/debug 'two
  ['one 1]
  ['two 2])

输出如下:

Case 2 <-- Printed
2      <-- Returned value

到目前为止,主要障碍是试图让表示已解决案例的数字正确显示。

我的目标是尝试编写一些可以像这样扩展的东西:

(match 'two
  ['one (displayln "Case 1") 1]
  ['two (displayln "Case 2") 2])

但我还没有找到任何方法来生成那些“Case #”字符串。

这是我尝试的宏定义:

(define-syntax-rule (match/debug id [pattern value] ...)
  (let ([index 0])
    (match id
      [(begin
         (set! index (add1 index))
         pattern)
       (printf "Case ~a\n" index)
       value] ...)))

似乎match 的语法不允许我做这样的事情,但这是我能想到的唯一方法。我只是真的习惯了 Common Lisp 的宏风格。

【问题讨论】:

    标签: macros scheme racket


    【解决方案1】:

    这里有一个解决方案。

    辅助函数clauses-&gt;numbers 返回从0 到小于子句数的数字的列表。然后使用它为每个子句赋予其自己的编号。请注意,此解决方案从 0 开始计数(而不是您的示例中的 1)。

    #lang racket
    (require (for-syntax syntax/parse))
    
    (begin-for-syntax
      (require racket/list) ; import range
      (define (clauses->numbers stx)
        (range (length (syntax->list stx)))))
    
    (define-syntax (match/debug stx)
      (syntax-parse stx
        [(_match/debug id [pattern value] ...)
         (with-syntax ([(n ...) (clauses->numbers #'([pattern value] ...))])
           (syntax/loc stx
             (match id
               [pattern (begin (displayln (~a "Case: " n)) value)]
               ...)))]))
    
    (match/debug 'one
      ['one 1]
      ['two 2])
    
    (match/debug 'two
      ['one 1]
      ['two 2])
    

    输出:

    Case: 0
    1
    Case: 1
    2
    

    【讨论】:

    • 有趣的是......我实际上最终使用了引用的模式,它给了我足够的信息。但感谢您快速而彻底的回复!
    猜你喜欢
    • 2019-09-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多