間でマクロを使用して、私は変更可能な構造体のフィールドをインクリメントするマクロを作成する方法について設定します。ラケット:自分自身のラケットでは、より高度なマクロを教えるためには、モジュール
(increment! instance name field)
=>
(set-name-field instance (get-name-field instance))
私はそのマクロを作成しました複数のモジュール間で共有することが有効であると判断しました。残念ながら、構造体のミューテータはマクロを定義するモジュールの範囲にないため、拡張エラーが発生します。
次は、この問題を示す意図した例です。私は知りたいです:
私は慣用ラケットスタイルでマクロコードを書いていますか?これは正しいアプローチですか?
マクロの展開を制御して、それが元のコンテキストにない識別子の存在下で動作するようにするにはどうすればよいですか?
ありがとう。
#lang racket/load
(module util racket
(define-syntax increment!
(lambda (stx)
(syntax-case stx()
[(increment! s sn fn i)
(with-syntax
([set! (string->symbol
(format "set-~a-~a!" (syntax-e #'sn) (syntax-e #'fn)))]
[get (string->symbol
(format "~a-~a" (syntax-e #'sn) (syntax-e #'fn)))])
#'(set! s (+ i (get s))))]
;; default increment of 1
[(increment! s sn fn) #'(increment! s sn fn 1)])))
(provide increment!)
)
(module bank racket
(require 'util)
(struct money (dollars pounds euros) #:mutable #:transparent)
(let ([m (money 0 50 20)])
(increment! m money pounds 100)
(increment! m money dollars)
m)
)
(require 'bank)
の業績は拡大:設定マネー・ポンド:内のモジュールで結合していない識別子を!
ありがとう@Eli Barzilay、文脈を注入すると非常に優雅に動作します。私は解決策がかなり堅牢ではないことに同意する、私は最終的に構文 - ケースを学ぶために良い言い訳としてそれを単にラッチした。私は確かにstruct-infoを使って改良しようとします。 – LazyBitStream