4

1 つの引数が渡されたときに機能するマクロがあり、... を使用して n 個の引数を受け入れるように拡張したいのですが、構文を理解するのに苦労しています。

マクロは、カスタム構文、つまり key:val key:val を受け入れるか、プロシージャを受け入れます。

例: (3 つの異なる使用法)

(schema-properties [(name:first-name type:string)])
(schema-properties [(name:age type:number required:#t)])
(schema-properties [(my-custom-fn arg1 arg2 arg3)])

意味:

(define-syntax (schema-properties stx)
  (syntax-parse stx
    [(_ [(prop:expr ...)])
     (with-syntax ([prop0 (make-prop-hash #'(prop ...))])
       #'(list prop0))]))

(define-for-syntax (make-prop-hash stx)
  (with-syntax ([(props ...) stx])
    (if (regexp-match #px":"
                      (symbol->string (car (syntax->datum #'(props ...)))))
        #'(pairs->hash 'props ...)
        #'(props ...))))

これは、":" の存在について prop:expr 構文をチェックし、存在する場合はそれを関数に渡し (pairs->hash 'props ...)、それ以外の場合はそれを呼び出す (props ...)。

今、私は渡すことができるようにしたいと思います:

(schema-properties [(name:first-name type:string)
                    (name:last-name type:string)
                    (my-fn arg1 arg2 arg3)])

同じように動作させます。しかし、私は現在、省略地獄に陥っており、私の脳はもはや正しく機能していません。

どんな洞察も高く評価されます。

4

2 に答える 2

4

推奨事項: ヘルパー関数を使用して、ネストに対処してください。マクロはネストの 1 つのレベルを処理する方法schema-propertiesを知っており、それを複数の節に適用したいと考えています。これは、モノのリストを処理するときと同じ原則です。モノを処理するヘルパーを用意し、それをリスト全体に適用します。複雑さを軽減するのに役立ちます。

コードの場合、次のようにできます。

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

(define-syntax (schema-properties stx)
  (syntax-parse stx
    [(_ [clause ...])
     (with-syntax ([(transformed-clauses ...)
                    (map handle-clause (syntax->list #'(clause ...)))])
       #'(list transformed-clauses ...))]))


;; handle-clause: clause-stx -> stx
(define-for-syntax (handle-clause a-clause)
  (syntax-parse a-clause
    [(prop:expr ...)
     (make-prop-hash #'(prop ...))]))


(define-for-syntax (make-prop-hash stx)
  (with-syntax ([(props ...) stx])
    (if (regexp-match #px":"
                      (symbol->string (car (syntax->datum #'(props ...)))))
        #'(pairs->hash 'props ...)
        #'(props ...))))


;;; Let's try it out.  I don't know what your definition of pairs->hash is,
;;; but it probably looks something like this:
(define (pairs->hash . pairs)
  (define ht (make-hash))
  (for ([p pairs])
    (match (symbol->string p)
      [(regexp #px"([-\\w]+):([-\\w]+)" 
               (list _ key value))
       (hash-set! ht key value)]))
  ht)

(schema-properties [(name:first-name type:string)
                    (name:last-name type:string)
                    (list 1 2 3)])
于 2013-04-17T20:33:00.903 に答える