[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Macros as 1st class objects
From: |
Taylan Kammer |
Subject: |
Re: Macros as 1st class objects |
Date: |
Tue, 12 Mar 2019 19:46:31 +0100 |
User-agent: |
Gnus/5.13 (Gnus v5.13) Emacs/26.1 (gnu/linux) |
Tk <address@hidden> writes:
> How likely is that something likes this,
> (define macro2 (module-ref (current-module) 'macro1))
>
> breaks in the future versions of Guile? The docs say this is
> low-level, so I have my suspicions.
>
> I have an application that defines abstract interface modules and
> specialises the names of the functions defined in it in other modules
> that get initialised based on user input. For normal procedures, this
> works fine. Applying the same principle to macros could work with the
> pattern above, but for that to make sense, i'd like to know that a)
> mechanism is stable to medium-term Guile evolution, b) the practice is
> not frowned upon.
>
> Tk
>
> Sent with [ProtonMail](https://protonmail.com) Secure Email.
Let's see if I can help. If I understood your issue correctly, then the
following should be what you need. (If I misunderstood, then sorry, it
was just a fun exercise for me. :-) )
Here's a syntax-case macro that lets you alias a name to any other,
where that 'other' is provided as a symbol object like in your code:
(define-syntax alias
(syntax-rules ()
((_ <newname> <oldname-expr>)
(define-syntax <newname>
(lambda (stx)
(syntax-case stx ()
((_ . args)
(cons (datum->syntax stx <oldname-expr>)
#'args))))))))
Example usage:
scheme@(guile-user)> (alias test 'display)
scheme@(guile-user)> (test "foo\n")
foo
How does this work? It's a macro-generating macro. When you use the
following code...
(alias test 'display)
...the 'alias' macro (writtin in syntax-rules) firstly turns that into
the following code:
(define-syntax test
(lambda (stx)
(syntax-case stx ()
((_ . args)
(cons (datum->syntax stx 'display)
#'args)))))
And that code in turn defines 'test' as a macro (written in syntax-case)
that takes any number of arguments, and creates the following code...
([['display' from the macro-call context]] arg1 arg2 ... argN)
...where I've used the pseudo-code [['display' from the macro call
context]] to denote a syntax-object which encapsulates the symbol
'display' together with the syntax-context that came from the 'stx'
object, which as you see I passed as an argument to 'datum->syntax'.
If this still seems like black magic, you might want to look closer into
how things like syntax-rules, syntax-case, or datum->syntax work, which
ever ones you're not familiar with yet.
Scheme macros are a fine art. :-) Lots of headache until you grasp them,
but then it's blissful.
Hope this was useful,
- Taylan