> On Aug 27, 2017, at 5:36 PM, Mark H Weaver <m...@netris.org> wrote: > > 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 >
Thanks. Things look much better now. I just added a case for define-foo syntax with an extra arg for wrap, so I can pass it. I wrapped gen-id in the eval-when. (Yay!) I replaced `(gen-id x "wrap-" #'name)' with `(gen-id #'name "wrap-" #'name)'. (I used to write the last step that way but picked up a bad habit at some time.) Matt