Home > Archive > Scheme > September 2006 > Bending hygiene with syntax-case
You are viewing an archived Text-only version of the thread.
To view this thread in it's original format and/or if you want to reply to
this thread please [click here]
| Author |
Bending hygiene with syntax-case
|
|
| oversby@hotmail.com 2006-09-09, 4:01 am |
| Hi,
I am trying to create a single argument anonymous function
using macros and I am having some difficulty introducing the
parameter name into the body of the function using
datum->syntax-object. I think it works the first time that
my-where-helper is called, but on subsequent recursive calls
it seems that the context information from stx is lost. Am
I misunderstanding the correct way to bend the hygiene
rules?
Ian
(define-syntax my-where-helper
(lambda (stx)
(syntax-case stx ()
((_) (syntax #t))
((_ e1 e2 e3 ...)
(syntax (and (let ((kw (get-keyword e1 (datum->syntax-object
(syntax stx) 'cd))))
(if kw (string=? kw e2) #t))
(my-where-helper e3 ...)))))))
(define-syntax my-where
(lambda (stx)
(syntax-case stx ()
((_ e0 e1 e2 ...)
(with-syntax ((tail (syntax (my-where-helper e0 e1 e2 ...))))
(syntax (lambda (cd) tail)))))))
((my-where #:abc "abc" #:xyz "xyz") '(#:abc "abc" #:xyz "xyz"))
| |
| Abdulaziz Ghuloum 2006-09-09, 4:01 am |
|
oversby@hotmail.com wrote:
> Hi,
>
> I am trying to create a single argument anonymous function
> using macros and I am having some difficulty introducing the
> parameter name into the body of the function using
> datum->syntax-object. I think it works the first time that
> my-where-helper is called, but on subsequent recursive calls
> it seems that the context information from stx is lost. Am
> I misunderstanding the correct way to bend the hygiene
> rules?
Yes you are. How about you give a simpler example that attempts to
bend hygiene and we work it out from there?
> (define-syntax my-where-helper
> (lambda (stx)
> (syntax-case stx ()
> ((_) (syntax #t))
> ((_ e1 e2 e3 ...)
> (syntax (and (let ((kw (get-keyword e1 (datum->syntax-object
> (syntax stx) 'cd))))
> (if kw (string=? kw e2) #t))
> (my-where-helper e3 ...)))))))
>
> (define-syntax my-where
> (lambda (stx)
> (syntax-case stx ()
> ((_ e0 e1 e2 ...)
> (with-syntax ((tail (syntax (my-where-helper e0 e1 e2 ...))))
> (syntax (lambda (cd) tail)))))))
Your my-where example is exactly the same as
(define-syntax my-where
(syntax-rules ()
[(_ e0 e1 e2 ...)
(lambda (cd) (my-where-helper e0 e1 e2 ...))]))
and my-where-helper is almost the same as:
(define-syntax my-where-helper
(let ([stx 'unused])
(syntax-rules ()
[(_) #t]
[(_ e1 e2 e3 ...)
(and (let ([kw (get-keyword e1 (datum->syntax-object (syntax
stx) 'cd))])
(if kw (string=? kw e2) #t))
(my-where-helper e3 ...))])))
So,
(my-where #:abc "abc" #:xyz "xyz")
expands to:
(lambda (cd.0) (my-where-helper #:abc "abc" #:xyz "xyz"))
expands to:
(lambda (cd.0)
(and (let ([kw.1 (get-keyword #:abc (datum->syntax-object (syntax
stx)) 'cd)])
(if kw.1 (string=? kw.1 "abc") #t))
(my-where-helper #:xyz "xyz")))
expands to:
(lambda (cd.0)
(and (let ([kw.1 (get-keyword #:abc (datum->syntax-object (syntax
stx)) 'cd)])
(if kw.1 (string=? kw.1 "abc") #t))
(and (let ([kw.2 (get-keyword #:xyz (datum->syntax-object
(syntax stx)) 'cd)])
(if kw.2 (string=? kw.2 "xyz") #t))
(my-where-helper))))
expands to:
(lambda (cd.0)
(and (let ([kw.1 (get-keyword #:abc (datum->syntax-object (syntax
stx)) 'cd)])
(if kw.1 (string=? kw.1 "abc") #t))
(and (let ([kw.2 (get-keyword #:xyz (datum->syntax-object
(syntax stx)) 'cd)])
(if kw.2 (string=? kw.2 "xyz") #t))
#t)))
This is not what you intended I guess.
Aziz,,,
| |
| oversby@hotmail.com 2006-09-09, 4:02 am |
| Hi Aziz,
Abdulaziz Ghuloum wrote:
> Yes you are. How about you give a simpler example that attempts to
> bend hygiene and we work it out from there?
>
> Your my-where example is exactly the same as
>
> (define-syntax my-where
> (syntax-rules ()
> [(_ e0 e1 e2 ...)
> (lambda (cd) (my-where-helper e0 e1 e2 ...))]))
>
> and my-where-helper is almost the same as:
>
> (define-syntax my-where-helper
> (let ([stx 'unused])
> (syntax-rules ()
> [(_) #t]
> [(_ e1 e2 e3 ...)
> (and (let ([kw (get-keyword e1 (datum->syntax-object (syntax
> stx) 'cd))])
> (if kw (string=? kw e2) #t))
> (my-where-helper e3 ...))])))
Hmmm... so my misunderstanding is pretty much
complete then :) I thought that stx is what gets
matched against stx so (_ e1 e2 e3 ...) is trying to
match whatever was passed to it from my-where.
But infact, it is not being used at all?
> So,
>
> (my-where #:abc "abc" #:xyz "xyz")
>
> expands to:
> (lambda (cd.0) (my-where-helper #:abc "abc" #:xyz "xyz"))
>
> expands to:
> (lambda (cd.0)
> (and (let ([kw.1 (get-keyword #:abc (datum->syntax-object (syntax
> stx)) 'cd)])
> (if kw.1 (string=? kw.1 "abc") #t))
> (my-where-helper #:xyz "xyz")))
>
> expands to:
> (lambda (cd.0)
> (and (let ([kw.1 (get-keyword #:abc (datum->syntax-object (syntax
> stx)) 'cd)])
> (if kw.1 (string=? kw.1 "abc") #t))
> (and (let ([kw.2 (get-keyword #:xyz (datum->syntax-object
> (syntax stx)) 'cd)])
> (if kw.2 (string=? kw.2 "xyz") #t))
> (my-where-helper))))
>
> expands to:
> (lambda (cd.0)
> (and (let ([kw.1 (get-keyword #:abc (datum->syntax-object (syntax
> stx)) 'cd)])
> (if kw.1 (string=? kw.1 "abc") #t))
> (and (let ([kw.2 (get-keyword #:xyz (datum->syntax-object
> (syntax stx)) 'cd)])
> (if kw.2 (string=? kw.2 "xyz") #t))
> #t)))
>
> This is not what you intended I guess.
>
> Aziz,,,
Infact, this end result is fairly close to what I intended. If only
(datum->syntax-object (syntax stx)) 'cd) expanded to cd.0
which I guess is the bit I'm having difficulty with.
Okay, a simpler example. Say I want a macro my-macro
that takes any number of parameters and expands it all to
a lambda function that checks if the keyword is in the
lambda parameter for each parameter passed to my-macro.
e.g.
(my-func #:abc #:def #:ghi)
should expand to
(lambda (x)
(and (get-keyword #:abc x)
(and (get-keyword #:def x)
(and (get-keyword #:ghi x)))
#t))
(define-syntax my-macro
(syntax-rules ()
[(_ e0 e1 ...)
(lambda (x) (my-helper e0 e1 ...))]))
(define-syntax my-helper
(lambda (stx)
(syntax-case stx ()
((_) (syntax #t))
((_ e1 e2 ...)
(syntax (and (get-keyword e1 (datum->syntax-object (syntax stx)
'x))
(my-helper e2 ...)))))))
((my-macro #:abc #:def #:ghi) '(#:abc "abc" #:def "def"))
And this presumably has the same problem that my previous
example has in that stx is not being used :-/
Ian
| |
| Abdulaziz Ghuloum 2006-09-09, 4:02 am |
|
oversby@hotmail.com wrote:
> ...
> Infact, this end result is fairly close to what I intended. If only
> (datum->syntax-object (syntax stx)) 'cd) expanded to cd.0
> which I guess is the bit I'm having difficulty with.
You don't need to break any hygiene to do this.
> Okay, a simpler example. Say I want a macro my-macro
> that takes any number of parameters and expands it all to
> a lambda function that checks if the keyword is in the
> lambda parameter for each parameter passed to my-macro.
>
> e.g.
>
> (my-func #:abc #:def #:ghi)
>
> should expand to
>
> (lambda (x)
> (and (get-keyword #:abc x)
> (and (get-keyword #:def x)
> (and (get-keyword #:ghi x)))
> #t))
>
> (define-syntax my-macro
> (syntax-rules ()
> [(_ e0 e1 ...)
> (lambda (x) (my-helper e0 e1 ...))]))
This is very close. Just modify my-macro to pass the x it creates to
my-helper:
(define-syntax my-macro
(syntax-rules ()
[(_ e0 e1 ...)
(lambda (x) (my-helper x e0 e1 ...))]))
> (define-syntax my-helper
> (lambda (stx)
> (syntax-case stx ()
> ((_) (syntax #t))
> ((_ e1 e2 ...)
> (syntax (and (get-keyword e1 (datum->syntax-object (syntax stx)
> 'x))
> (my-helper e2 ...)))))))
Now make my-helper take the x and use it:
(define-syntax my-helper
(syntax-rules ()
[(_ x) #t]
[(_ x e1 e2 ...)
(and (get-keyword e1 x)
(my-helper x e2 ...))]))
And that's all there is to it. No dirty business :-)
Aziz,,,
| |
| oversby@hotmail.com 2006-09-09, 4:02 am |
| Abdulaziz Ghuloum wrote:
> This is very close. Just modify my-macro to pass the x it creates to
> my-helper:
>
> (define-syntax my-macro
> (syntax-rules ()
> [(_ e0 e1 ...)
> (lambda (x) (my-helper x e0 e1 ...))]))
>
> Now make my-helper take the x and use it:
>
> (define-syntax my-helper
> (syntax-rules ()
> [(_ x) #t]
> [(_ x e1 e2 ...)
> (and (get-keyword e1 x)
> (my-helper x e2 ...))]))
>
> And that's all there is to it. No dirty business :-)
>
> Aziz,,,
Thanks very much Aziz. I'll work through that to see
if it makes a bit more sense to me :)
Cheers,
Ian
|
|
|
|
|