2016-02-02 51 views
2

這是場景:給定[sym ...](例如和[a b c d])形式的模式我想要生成(使用宏)連接模式中的符號的函數,但也提供他們作爲論據。例如,轉變爲形式使用語法列表作爲函數的形式參數

(define (ab a b) 
    body) 

this post有人幫助我通過所謂signal-list語法類生成函數的名稱的東西。在下面的代碼中,我可以將signals模式變量與(sig ...)格式的模式匹配,然後我可以使用它來生成所需的函數定義。

(define-syntax (define-something stx) 
    (syntax-parse stx 
    [(_ (signals:signal-list body ...)) 
    (syntax-parse #'signals 
     [(sig ...) 
     #'(define (signals.concatenated-ids sig ...) 
       body ...)])])) 

,這個宏觀匹配的例子:

(define-something 
    ([a b] 'body)) 

它擴展到(define (ab a b) 'body)

但如何宏的工作,如果我想生成多個函數的定義?例如:

(define-something 
    ([a b] 'body) 
    ([c d e] 'body)) 
=> 
(begin (define (ab a b) 'body) 
     (define (cde c d e) 'body)) 

我可以在第一語法解析的方式添加一個省略號:

(_ (signals:signal-list body ...) ...)

但我不能使用第二語法解析來匹配signals,因爲它需要省略號。有沒有不同的方式來'去構造'signals,以便我可以使用它的內容作爲函數的形式參數,這與使用橢圓相兼容?

+1

的[回答你提到](http://stackoverflow.com/a/34777089/343414)已經定義了多種功能,所以,我不確定你在這裏問什麼?請注意,該答案適用,因爲它在模式和模板中都使用相同數量的省略號。 –

+0

它的確如此,我理解它爲什麼會這樣做,但隨着提供組合ID作爲形式參數的額外要求,我非常困惑。我應該對語法類進行更多的研究,以正確理解正在發生的事情。我相信答案相當微不足道。宏的Racket文檔對於那些不會在早餐時不使用宏的人來說並不那麼友好。 – Sam

+2

這聽起來像你正在尋找定義新的模式變量。 'syntax-parse'是一種(相當重量級)的方式。正如Chris所建議的,'with-syntax'是定義局部模式變量的一種更簡單的方法。用'syntax-parse'定義局部模式變量的慣用方式是用'#:with' [pattern directive](http://docs.racket-lang.org/syntax/stxparse-specifying.html?q=% 23%3Awith#%28tech._pattern._directive%29),例如'#:with((sig ...)...)#'signals' – stchang

回答

2

要直接回答您的問題,您可以將#'(signals ...)(代替您現有的#'signals)傳遞給內部syntax-parse調用。


由於概念證明,我寫了一個syntax-case版本的宏(因爲我不知道syntax-parse還)。你應該能夠在相同的技術適應syntax-parse容易:

(define-syntax (define-something outerstx) 
    (define (make-name paramstx) 
    (datum->syntax outerstx 
        (string->symbol 
        (apply string-append 
          (map symbol->string (syntax->datum paramstx)))))) 

    (define (make-names innerstx) 
    (syntax-case innerstx() 
     (() 
     #'()) 
     (((param ...) rest ...) 
     (with-syntax ((name (make-name #'(param ...))) 
        ((next ...) (make-names #'(rest ...)))) 
     #'(name next ...))))) 

    (syntax-case outerstx() 
    ((_ ((param ...) body ...) 
     ...) 
    (with-syntax (((name ...) (make-names #'((param ...) ...)))) 
     #'(define-values (name ...) 
      (values (lambda (param ...) 
        body ...) 
        ...)))))) 
+1

謝謝您的回答,它引導我找到解決方案。如果其他人遇到這個問題:我不是使用內部語法分析,而是使用'with-syntax'來匹配''('sig ...)...'與'#'(信號。 ..)'語法。第一個語法分析的主體看起來像這樣:'(with-syntax([((sig ...)...)#'(signals ...)])#'())'。我所缺乏的關鍵洞察力是,通過_pattern matching_確實可以「解構」事物。這對我來說應該很明顯,但事實並非如此。謝謝! – Sam

+3

刪除文字列表,並且'syntax-parse'是對'syntax-case'的直接替換:) – stchang