Racket's syntax-expander deliberately goes out of its way to break exactly
this example.  ("hygiene")

The issue/bug/ambiguity it is protecting you from is:
  (let ((send (lambda args (length args)) ))
    (def (foo3 x y)
       (send x + y)
     ))
  (foo3 2 3) ;; In lisps with poor grooming, 5.  In racket, 3.  3 is not
what you wanted this time, but it is the better default behavior overall.


There are many ways to get exactly the desired syntactic behavior; syntax
parameters work, as does datum->syntax.


If you're willing to bend a little, a more racket-y solution, it seems to
me, is to force the user of the syntax to give you a name, like:
  (define-syntax-rule (with-SVO-as name body ...) (let-syntax ((name
(syntax-rules [(_ s v o ...) (v s o ...)] ))) body ...)

Which can be used like:
  (define (foo4 x y) (with-SVO-as send (send x + y)))

Or like:
  (define-syntax send (with-SVO-as n n))
  (define (foo5 x y) (send x + y))

Or like:
  (define (foo6 x y) (define-syntax send (with-SVO-as n n)) (send x + y))


That approach doesn't work so well for things like:
  (with-slots  (x y z) (person-x person-y person-z) the-person
    (sqrt (* x x) (* y y) (* z z)))

That is, when there are lots of names to be bound, and they're pretty much
always the same, then the repetition/renaming at each use-site gets quite
tiresome; that is the problem that modules solve.

-Will


On Thu, Sep 3, 2015 at 9:59 AM, Brian Mastenbrook <br...@mastenbrook.net>
wrote:

> On Sep 3, 2015, at 11:44, Konrad Hinsen <konrad.hin...@fastmail.net>
> wrote:
>
> > Hi everyone,
> >
> > Here's another plea for help from the macro experts. I am trying to
> > write a macro whose expansion contains another macro, more precisely a
> > let-syntax form. My full example is attached below. In the first part,
> > I use a let-syntax directly. In the second part, I use a macro that
> > generates exactly the form that I wrote by hand in the first part -
> > but then the let-syntax seems to be ignored.
> >
> > The macro stepper isn't of much help here. It shows the expansion
> > of (defn (foo2 ...)) into essentially what I wrote by hand for foo1,
> > and then declares the expansion finished.
> >
> > Can anyone tell me (1) why this doesn't work and (2) how to fix it?
>
> It's a capture problem. In the first case, you're just binding the name
> "send" locally and all is well. In the second case, you're trying to
> introduce a binding for "send" that you didn't get from the input form.
> You're also getting a confusing error because "send" is already bound; try
> using a name that's not already defined and you should get an unbound
> identifier.
>
> You can fix this in one of two ways. Your `def' macro could take the name
> of the `send' macro it binds as a parameter, which gets a little ugly.
> Alternatively, you can use a syntax parameter, which is probably the ideal
> solution here.
>
> (require (for-syntax syntax/parse))
> (require racket/stxparam)
>
> (define-syntax-parameter send (lambda (stx) (raise-syntax-error 'send
> "send used out of context")))
>
> (define-syntax (def stx)
>  (syntax-parse stx
>    [(_ (fn-name:id arg:id ...) body ... )
>     #'(define (fn-name arg ...)
>         (syntax-parameterize ([send (λ (stx)
>                                       (syntax-parse stx
>                                         [(send obj:expr method:id x:expr
> (... ...))
>                                          #'(method obj x (... ...))]))])
>                              body ...))]))
>
> (def (foo2 x y)
>  (send x + y))
>
> (foo2 2 3)
>
>
> --
> Brian Mastenbrook
> br...@mastenbrook.net
> http://brian.mastenbrook.net/
>
> --
> You received this message because you are subscribed to the Google Groups
> "Racket Users" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to racket-users+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.
>

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to