Am Fr., 6. März 2020 um 16:44 Uhr schrieb John Cowan <xxxxxx@ccil.org>:


On Fri, Mar 6, 2020 at 9:55 AM Marc Nieper-Wißkirchen <xxxxxx@nieper-wisskirchen.de> wrote:

The "conflating" form of `lambda/kw' is furthermore dangerous when used in macros: Assume `(lambda/kw (x y (z)) ... w ...)' is in the template of a macro where `z' and `w' are macro parameters. For the macro writer everything looks fine but it will make boom when the macro user supplies the same macro parameter for `z' and `w'.

Can you spell this out in detail with an example?  I have a fairly concrete mind (which is not to say that it is actually made of concrete).

:)

So here is a minimal example:

(define-syntax my-macro
  (syntax-rules ()
    ((_ keyword proc)
     (lambda/kw ((keyword))
       (proc keyword)))))

The idea is that `(my-macro <name> <proc>)' evaluates to a procedure that takes a single keyword argument named <name> and calls to what <proc> evaluates with that keyword.

For example (using the new syntax proposal), `(call (my-macro foo list) /kw foo 1)' will evaluate to `'(1)'.

On the other hand, `(call (my-macro list list) /kw list 1)' will evaluate to `(1 1)' and thus an error.

If you want to repair that macro, note that

(define-syntax my-macro
  (syntax-rules ()
    ((_ keyword proc)
     (let ((p proc))
       (lambda/kw ((keyword))
         (p keyword)))))

is not a faithful correction. In contrast to the original version, `proc' will be only evaluated once and not every time the generated keyword procedure is called.

A faithful correction would be

(define-syntax my-macro
  (syntax-rules ()
    ((_ keyword proc)
     (let-syntax ((p (syntax-rules () ((p) proc))))
       (lambda/kw ((keyword))
         ((p) keyword)))))

Here, thanks to hygiene of the inner macro, any variables in <proc> are free in the body of lambda/kw.  As you can see it is possible to somehow work around the limitations of the original `lambda/kw' proposal but it is cumbersome. That such workarounds are necessary is, in my opinion, a clear sign the original `lambda/kw' proposal is missing a way to name the inserted identifiers differently than the keywords.

Marc

PS: Too bad that your pun doesn't work in German. You can talk about a "Betonkopf", but "concrete" is just "konkret", which has nothing to do with the building sector.