Macros 在球拍宏中使用新关键字

Macros 在球拍宏中使用新关键字,macros,scheme,racket,Macros,Scheme,Racket,作为对Racket的练习,我尝试创建一个类似C的函数,接受return关键字 定义函数时宏: (require (for-syntax syntax/parse)) (define-syntax (function stx) (syntax-parse stx #:datum-literals (return) [(_ (func-id arg-id ...) body ...) #'(define (func-id arg-id ...) (c

作为对Racket的练习,我尝试创建一个类似C的函数,接受
return
关键字

定义
函数时
宏:

(require (for-syntax syntax/parse))
(define-syntax (function stx)
  (syntax-parse stx
    #:datum-literals (return)
    [(_ (func-id arg-id ...)  body ...)
     #'(define (func-id arg-id ...)
         (call/cc (lambda (return) body ...)))]))
(require macro-debugger/expand)
(syntax->datum (expand-only
                #'(function (f x) (return 100) (+ 1 x))
                (list #'function)))
并使用
return
语句创建函数
f

(function (f x) (return 100) (+ 1 x))
(f 2)
我得到:

return: undefined;
cannot reference an identifier before its definition
但是,展开
函数
宏:

(require (for-syntax syntax/parse))
(define-syntax (function stx)
  (syntax-parse stx
    #:datum-literals (return)
    [(_ (func-id arg-id ...)  body ...)
     #'(define (func-id arg-id ...)
         (call/cc (lambda (return) body ...)))]))
(require macro-debugger/expand)
(syntax->datum (expand-only
                #'(function (f x) (return 100) (+ 1 x))
                (list #'function)))
返回:

'(define (f x) (call/cc (lambda (return) (return 100) (+ 1 x))))
事实上:

(define (f x) (call/cc (lambda (return) (return 100) (+ 1 x))))
(f 2)
> 100
一切正常

对于我的虚拟案例,可以替换
函数
定义中的模式匹配,如下所示:

[(_ (func-id arg-id ...) (return x-expr) body ...)
 #'(define (func-id arg-id ...)
     (call/cc (lambda (return) (return x-expr) body ...)))]
但是一般来说,
return
关键字可以出现在函数体的任何地方


我该怎么做

我认为您误解了
基准文本的含义<代码>基准文本
用于模式匹配输入语法,而不是输出模板/语法

你试图做的事情不能仅仅通过重写规则来完成,因为Racket的卫生宏系统会将你的
return
重命名为其他名称,以避免名称冲突

通常的方法是使用syntax参数。已经很好地解释了这一点,所以我不再在这里重复了。

这似乎有效:

(require (for-syntax syntax/parse))
(require racket/stxparam)
(define-syntax-parameter return
  (lambda (stx)
    (raise-syntax-error (syntax-e stx) "can only be used inside aif")))

(define-syntax (function stx)
  (syntax-parse stx
    [(_ (func-id arg-id ...) body ...)
     #'(define (func-id arg-id ...)
         (call/cc (lambda (return_k)                      
                    (syntax-parameterize ([return (syntax-rules () [(_ val) (return_k val)])])
                      body ...))))]))
(function (f x) (return 100) (+ 1 x))
(f 2)

我想
syntax parameterize
可以通过
make rename transformer
来改进,但我没有成功

我仍然无法应用
make rename transformer
,无论如何,我获得了一个工作代码。看看我的答案,谢谢。我希望我需要一个参数
(make rename transformer#'(return_k val))