From: Stefan Israelsson Tampe <stefan.itampe@gmail.com>
To: Panicz Maciej Godek <godek.maciek@gmail.com>
Cc: "guile-user@gnu.org" <guile-user@gnu.org>,
Ian Price <ianprice90@googlemail.com>
Subject: Re: and-let* is not composable?
Date: Sat, 14 Sep 2013 10:19:07 +0200 [thread overview]
Message-ID: <CAGua6m32sxMyFDGmn_xa-3jxuHEuLDNPbw+VqFm--YLNHcdNKA@mail.gmail.com> (raw)
In-Reply-To: <CAMFYt2ajbs8OjNPvsyEygf6Qr-2T61QS_yWn+2EUSre2opP9iQ@mail.gmail.com>
[-- Attachment #1: Type: text/plain, Size: 6718 bytes --]
Hi,
Yes I agree that we should have good documentation to show how to
implement more advanced macros. The main reason (I beleve) for the "experts"
to spend time using syntax-case let-syntax syntax-parameters etc is for
yielding a user friendly framework to the user who will typically use
syntax-rules. If we would stick with defmacros or define-macro we would
push the burden to the novice end user and not to the expert. Now this is
what hygiene buy's you, and what it cost. Sticking to define-macros would
mean that we will get plenty of bug's caused by leaking macros and we would
spend a considerable time on guile-user and irc to hunt down these bug's.
Also In guile and most schemes we have standardized on this setup and not
complying to the standard essentially means that you are out of thee
cooperation.
But I think that your good point is that we should create/link to good
documentation for
the syntax-case system and essentially explain the model one needs to have
in the head in
order to use it effectively.
Regards
Stefan
On Fri, Sep 13, 2013 at 8:40 PM, Panicz Maciej Godek <godek.maciek@gmail.com
> wrote:
> > Well, while syntax-rules macros are quite easy to understand
>
>> > (at least from the user's point of view), although sometimes a little
>> > tricky, the syntax-case system I find still too difficult to use.
>> > define-macro, on the other hand, is very easy to explain
>> > even to beginner programmers, although the resulting macros
>> > are much more difficult to analyse.
>> If you, or the other people who are confused by syntax-case, can point
>> to the parts of the manual that confuse you, so we can clear them up, I
>> think we'd all appreciate it.
>>
>>
> The order of presentation in the manual is that syntax-rules macros
> are explained first, because they are more limited, and there's no
> need to get into details regarding syntax objects.
>
> I used to explain the "syntax-rules" macros to my friends by
> first showing "what we want to transform into what", and then packing
> it up in some magic to work (because basically that's how I
> understand them). The advantage was that the meaning of the macro
> is readily visible and there's no need to analyse the code.
>
> The manual however makes very little reference to define-macro system
> to explain how syntax-case works. It is easy to see that lisp programs
> are lists of symbols, and so they can be processed like any other
> lists of symbols before they are evaluated -- that's the essentials
> of lisp macros. In case of "syntax-case" some new mysterious
> notions appear: namely, the unfamous syntax objects. And while it
> is easy to imagine how the list of symbols look like, all we read
> about in the manual is that "the syntax expander represents
> identifiers as annotated syntax objects, attaching such information
> to those syntax objects as is needed to maintain referential
> transparency". We don't know what sort of information is that, and
> why is it better to use syntax-case over define-macro.
>
> Especially if we compare the "anamorphic if" definition from the
> manual,
> (define-syntax aif
> (lambda (x)
> (syntax-case x ()
> ((_ test then else)
> (syntax-case (datum->syntax x 'it) ()
> (it
> #'(let ((it test))
> (if it then else))))))))
>
> with the most straightforward "anamorphic if" with define-macro:
>
> (define-macro (aif test then else)
> `(let ((it ,test))
> (if it
> ,then
> ,else)))
>
> (Even if the latter is not exactly right, as is argued in section
> 6.10.5, it generally does its job)
>
> Also, I have to admit that I still don't understand what the
> syntax-case macro above is doing. Furthermore, it isn't clear why
> syntax->datum takes only one argument, and datum->syntax takes
> two (a syntax object and the "datum" itself)
>
>
>
>> Fundamentally, syntax-case shouldn't be harder to use than define-macro
>> 99% of the time, if you remember
>>
>> - macros are functions from "syntax-objects" to syntax-objects
>> - syntax-objects are smart symbols
>> - syntax->datum to remove the smartness
>> - datum->syntax is for when you want to break hygiene (but syntax
>> parameters are better where applicable)
>> - use quasisyntax to construct lists of syntax-objects instead of
>> quasiquote to construct lists of symbols.
>>
>
>
> Maybe showing a sufficient number of examples would be
> more helpful, because I haven't got a clue "where syntax
> parameters are applicable" or how I could use quasisyntax
> and unsyntax.
>
> By the way, I've had another problem when defining a macro.
> I've been trying to implement something like dynamical scoping,
> but such that it wouldn't require introducing global variables
>
> The idea is that one can write
>
> (with-default ((a 5))
> (define (f x) (+ x (specific a))))
>
> and that later the procedure could be used like that:
> (f 10)
> ===> 15
> (specify ((a 20))
> (f 10))
> ===> 30
>
> The first attempt was that there could be a global hash table
> *specifics* that would store the lists of values, and that
> "specific" could be a local macro that would expand to a hash
> reference. So I tried to implement that using syntax-rules
> in the following way:
>
> (define-syntax with-default
> (syntax-rules ()
> ((_ ((name value) ...)
> actions ...)
> (let-syntax ((specific (syntax-rules (name ...)
> ((_ name)
> (hash-ref *specifics* 'name value))
> ;; don't mind shadowing for now
> ...)))
> actions ...))))
>
> However, when I tried to use it, it seemed that the let-syntax
> behaves as if it wasn't there (so it didn't behave at all!):
>
> (with-default ((a 5))
> (define (f x)(+ x (specific a))))
>
> The situation was (again) resolved by creating a nasty combination
> of "define-macro" and "syntax-rules", namely:
>
> (define-macro (with-default bindings . actions)
> (match bindings
> (((names values) ...)
> `(let-syntax ((specific (syntax-rules ,names
> ,@(map (match-lambda
> ((name value)
> `((_ ,name)
> (hash-ref *defaults*
> ',name ,value))))
> bindings))))
> ,@actions))))
>
> It's not that I like it. I really don't. But I don't know how how
> else this could be achieved, nor why the former solution
> so stubbornly resists to work.
>
> Thanks,
> M.
>
>
[-- Attachment #2: Type: text/html, Size: 9658 bytes --]
next prev parent reply other threads:[~2013-09-14 8:19 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-09-09 17:35 and-let* is not composable? Panicz Maciej Godek
2013-09-09 20:26 ` Stefan Israelsson Tampe
2013-09-09 21:34 ` Ian Price
2013-09-10 13:42 ` Stefan Israelsson Tampe
2013-09-10 13:51 ` Ian Price
2013-11-02 2:39 ` Ian Price
2013-11-02 19:01 ` Ian Price
2013-09-10 17:57 ` Ian Price
2013-09-11 12:25 ` Panicz Maciej Godek
2013-09-11 14:05 ` Ian Price
2013-09-13 18:40 ` Panicz Maciej Godek
2013-09-14 8:19 ` Stefan Israelsson Tampe [this message]
2013-10-04 22:27 ` Panicz Maciej Godek
2013-10-05 8:00 ` Ian Price
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
List information: https://www.gnu.org/software/guile/
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=CAGua6m32sxMyFDGmn_xa-3jxuHEuLDNPbw+VqFm--YLNHcdNKA@mail.gmail.com \
--to=stefan.itampe@gmail.com \
--cc=godek.maciek@gmail.com \
--cc=guile-user@gnu.org \
--cc=ianprice90@googlemail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).