For Programmers: Free Programming Magazines  


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

Sponsored Links







Also available: Server administration forum archive | Web Design forum archive | Software forum archive | Hardware reviews archive

Copyright 2008 codecomments.com