macros - 宏定义中的升序数字

标签 macros scheme racket

我经常使用 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 的宏风格。

最佳答案

这是一个解决方案。

辅助函数 clauses->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

关于macros - 宏定义中的升序数字,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38576490/

相关文章:

c++ - 向类 : using macro function into header file 添加动态方法

matrix - 函数式编程中的有效矩阵

scheme - 方案中的条件定义

scheme - Racket中如何判断两个struct实例是否属于同一结构类型?

scheme - 想要在程序未运行时更改 Racket GUI 应用程序标题(在任务栏上)

方案:如何将用 cons 制成的列表更改为向量?

macros - 使用 memfn 定义函数

clojure - 线程优先、线程最后和 "dot"形式

C++:将基于宏的属性系统转换为使用模板

stream - Racket :采取:违反契约(Contract)