[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: problems with syntax-case and with-syntax
From: |
Matt Wette |
Subject: |
Re: problems with syntax-case and with-syntax |
Date: |
Sun, 27 Aug 2017 20:48:29 -0700 |
> On Aug 27, 2017, at 5:36 PM, Mark H Weaver <address@hidden> wrote:
>
> Matt Wette <address@hidden> 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