簡體   English   中英

在球拍宏中使用新關鍵字

[英]Using new keywords in Racket macros

作為Racket的練習,我試圖創建一個類似於C的函數,接受return關鍵字。

當我定義function宏時:

(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 ...)))]))

並使用return語句創建函數 f

(function (f x) (return 100) (+ 1 x))
(f 2)

我得到:

return: undefined;
cannot reference an identifier before its definition

但是,擴展function宏:

(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

如預期般運作。

對於我的虛擬情況,可以像這樣在function定義中替換模式匹配:

[(_ (func-id arg-id ...) (return x-expr) body ...)
 #'(define (func-id arg-id ...)
     (call/cc (lambda (return) (return x-expr) body ...)))]

但是通常, return關鍵字可以出現在函數體內的任何位置。

我怎樣才能做到這一點?

我認為您誤會了datum-literals意思。 datum-literals用於模式匹配輸入語法,而不用於輸出模板/語法。

您嘗試做的事情完全不能通過重寫規則來完成,因為Racket的衛生宏系統會將您的return重命名為其他名稱,以避免名稱沖突。

通常的方法是使用語法參數。 恐懼宏已經很好地解釋了這一點,因此在此不再贅述。

這似乎可行:

(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)

我想可以使用make-rename-transformer改進syntax-parameterize ,但是我沒有成功。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM