Matt Wette <matt.we...@gmail.com> writes: > Q1) The code below creates two macros. One called `define-foo' which > generates a new identifier and > then defines that to #t. The other, `define-foo/p', generates the same > identifier (lexical issue?) > and another identifier, then "calls" define-foo and then uses both > identifiers in a `define'. When > executed I get this error: > > scheme@(guile-user)> (define-foo/p abc) > ;;; <stdin>:2:0: warning: possibly unbound variable `wrap-abc' > <unnamed port>:2:0: <unnamed port>:2:0: In procedure module-lookup: Unbound > variable: wrap-abc > > What am I doing wrong here?
The problem is that in Guile 2.2, whenever (define <id> ...) is found in the expanded code, where <id> was introduced by a macro (i.e. not passed as an explicit argument to the macro), Guile will rewrite the <id> into a new name based on the hash of the entire definition form. I don't know of any way to make this work without passing 'wrap-abc' explicitly as an argument to the 'define-foo' macro. FWIW, I've always been opposed to these non-standard semantics, but they were included in Guile 2.2 over my strenuous objections: https://lists.gnu.org/archive/html/guile-devel/2014-01/msg00061.html https://lists.gnu.org/archive/html/guile-devel/2011-11/msg00021.html https://lists.gnu.org/archive/html/guile-devel/2011-11/msg00042.html > Q2) Also with respect to the code below. Is there any way to pull the > definitions for stx->str and gen-id out of the define-syntax body to > make them general purpose? Yes, you can wrap the definitions of 'stx->str' within 'eval-when', like this: (eval-when (expand load eval) (define (stx->str stx) ...) (define (gen-id tmpl-id . args) ...)) above the macro definitions that use them. One more thing: > (define-syntax define-foo > (lambda (x) > (define (stx->str stx) > (symbol->string (syntax->datum stx))) > (define (gen-id tmpl-id . args) > (datum->syntax > tmpl-id > (string->symbol > (apply string-append > (map (lambda (ss) (if (string? ss) ss (stx->str ss))) args))))) > (syntax-case x () > ((_ name) > (with-syntax ((wrap (gen-id x "wrap-" #'name))) > #'(begin > (define wrap #t))))))) Here, the 'tmpl-id' that is being passed to 'datum-syntax' is not actually an identifier, but rather a compound syntax object. Although we do not currently raise an error in this case (we probably should), it is against the spec and likely to cause problems in the future, if not today. You should pass an actual identifier as 'tmpl-id'. Regards, Mark