* Help: equivalent syntax-case to defmacro
@ 2020-05-05 17:34 Dale Mellor
2020-05-06 15:49 ` Taylan Kammer
0 siblings, 1 reply; 2+ messages in thread
From: Dale Mellor @ 2020-05-05 17:34 UTC (permalink / raw)
To: guile-user
Been struggling with this for a while, and nothing I try works.
In test-suite/tests/getopt-long there is
(defmacro deferr (name-frag re)
(let ((name (symbol-append 'exception: name-frag)))
`(define ,name (cons 'quit ,re))))
(deferr no-such-option "no such option")
(display exception:no-such-option)
and I would like to know how the equivalent with define-syntax... syntax-case would look.
Thanks,
Dale
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: Help: equivalent syntax-case to defmacro
2020-05-05 17:34 Help: equivalent syntax-case to defmacro Dale Mellor
@ 2020-05-06 15:49 ` Taylan Kammer
0 siblings, 0 replies; 2+ messages in thread
From: Taylan Kammer @ 2020-05-06 15:49 UTC (permalink / raw)
To: Dale Mellor, guile-user
On 05.05.2020 19:34, Dale Mellor wrote:
> Been struggling with this for a while, and nothing I try works.
>
> In test-suite/tests/getopt-long there is
>
> (defmacro deferr (name-frag re)
> (let ((name (symbol-append 'exception: name-frag)))
> `(define ,name (cons 'quit ,re))))
>
> (deferr no-such-option "no such option")
> (display exception:no-such-option)
>
> and I would like to know how the equivalent with define-syntax... syntax-case would look.
(define-syntax deferr
(lambda (s)
(syntax-case s ()
((_ name-frag re)
(let* ((name-frag-sym (syntax->datum #'name-frag))
(name-sym (symbol-append 'exception: name-frag-sym))
(name (datum->syntax #'name-frag name-sym)))
#`(define #,name (cons 'quit re)))))))
Some notes to help understand this:
- Syntax-case deals with syntax objects rather than raw symbols. We use
syntax->datum to turn 'name-frag' into a symbol and datum->syntax to
turn it back into a syntax object.
- For some reason, the pattern variables bound via syntax-case (i.e.
'name-frag' and 're' in our case) are forbidden by syntax-case to be
referenced outside of a #' or #` form. They must always appear in one
of those, period. Hence we have to call (syntax->datum #'name-frag)
instead of simply (syntax->datum name-frag). Honestly I still don't
know why they designed it this way.
- The datum->syntax form requires its first argument to be an existing
syntax object, which will tell datum->syntax for which "syntax context"
you're creating your new syntax object. In this case I'm passing it
#'name-frag because the context where that comes from is the context in
which the resulting full name will be used.
- In the output form starting with #` the 're' pattern variable can
appear naked, whereas the manually created 'name' syntax object must be
inserted with the #, form. (This is related to the same design
weirdness I mentioned before so don't ask me why.)
Hope that helps! Happy to answer further questions. Syntax-case is
very tricky but once you get it, it's amazing.
- Taylan
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2020-05-06 15:49 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2020-05-05 17:34 Help: equivalent syntax-case to defmacro Dale Mellor
2020-05-06 15:49 ` Taylan Kammer
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).