guile-user
[Top][All Lists]
Advanced

[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



reply via email to

[Prev in Thread] Current Thread [Next in Thread]