球拍:宏在匹配模式内扩展

Ben*_*man 4 macros racket

有没有办法检测宏是否在模式匹配中扩展?

这是我想写的一个示例宏,但它在一个内部失败match-define:

#lang racket/base
(require racket/match (for-syntax racket/base syntax/parse))

(struct point (x y))

(define-syntax (friendly-point stx)
  (syntax-parse stx
   [(_ arg* ...)
    #'(begin (printf "Now making a point\n") (point arg* ...))]
   [_ #'(begin (printf "Hello point\n") point)]))

(define p (friendly-point 1 2))
 ;; Prints "Now making a point"

(match-define (friendly-point x y) p)
;; ERROR
Run Code Online (Sandbox Code Playgroud)

Ale*_*ing 6

是.而不是使用创建的普通语法转换器define-syntax,用于define-match-expander创建可以配合 的宏match.

(require (for-syntax syntax/parse))

(define-match-expander positive
  (syntax-parser
    [(_ n)
     #'(? positive? n)]))

(match 3
  [(positive n) (~a n " is positive")])
; => "3 is positive"
Run Code Online (Sandbox Code Playgroud)

define-match-expander形式是灵活:它可以用来创建可宏只能内部使用match,但它也可以用于创建扩展不同,这取决于它们是如何通过提供两个变压器功能,每一个上下文中使用宏.这允许您具有"上下文相关"标识符,这些标识符既可用作函数,也可用作匹配扩展器.

(require (for-syntax syntax/parse)
         (prefix-in base: racket/base))

(define-match-expander syntax
  (syntax-parser
    [(_ x)
     #'(? syntax? (app syntax->datum x))])
  (make-rename-transformer #'base:syntax))

(match (syntax (1 2 3))
  [(syntax n) (~a n " is a syntax list")])
Run Code Online (Sandbox Code Playgroud)

如果您需要更多灵活性,可以define-match-expander完全放弃并使用prop:match-expander结构类型属性定义自定义结构.这可以与prop:procedure实现上述双参数功能相结合,但它也可以保持状态,并且它可以与其他结构类型属性配对,例如prop:rename-transformer允许相同的标识符在许多不同的上下文中起作用.


Lei*_*sen 5

你在寻找什么define-match-expander.它允许您创建在模式匹配上下文中扩展的宏.(另外,因为它有两个thunk,你可以有一个变体,当不在匹配的上下文时也使用.接下来,我应该指出

接下来,您可以在a的模板内部具有打印副作用define-match-expander,但您可以在宏本身中使用.(不过要注意的是,副作用将不会发生,如果你的模块已经被扩大,这是更详细地解释在本文中.

因此,使用匹配扩展器,包括在匹配之外使用的第二个函数,您将获得以下代码:

#lang racket/base

(require racket/match (for-syntax racket/base syntax/parse))

(struct point (x y))

(define-match-expander friendly-point
  (lambda (stx)
    (syntax-parse stx
      [(_ arg* ...)
       (printf "Now matching a point\n")
       #'(point arg* ...)]
      [_ #'point]))
  (lambda (stx)
    (syntax-parse stx
      [(_ args* ...)
       #'(begin (printf "Now making a point\n") (point args* ...))])))

(define p (friendly-point 1 2))
 ;; Prints "Now making a point"

(match-define (friendly-point x y) p)
;; Works fine now
Run Code Online (Sandbox Code Playgroud)