On Feb 12, 2015, at 9:53 AM, Konrad Hinsen <konrad.hin...@fastmail.net> wrote:
> I am trying to clean up some lengthy syntax-class definitions, but I > am running into a problem. Here's a much-simplified example: > > ---------------------------------------------------------------------- > #lang racket > > (require (for-syntax syntax/parse)) > > (define-syntax (foos-of-bars stx) > > (define-syntax-class foo > #:attributes (value) > (pattern ((~datum foo) foo-symbol:id ... ((~datum bar) bar-symbol:id) ...) > #:with value > #'(let ([foo-symbols (set (quote foo-symbol) ...)]) > (list 'foo > (list 'bar > (if (set-member? foo-symbols (quote bar-symbol)) > (list (quote bar-symbol)) > (quote bar-symbol))) ...)))) > > (syntax-parse stx > [(_ foo:foo ...) > #'(list foo.value ...) ])) > > (foos-of-bars (foo x y (bar a) (bar x))) > ---------------------------------------------------------------------- > > I have several patterns like 'foo', and they all share the same 'bar' > subpattern. Therefore I would like to make 'bar' a syntax class of its > own: > > ---------------------------------------------------------------------- > (define-syntax (foos-of-bars stx) > > (define-syntax-class foo > #:attributes (value) > (pattern ((~datum foo) symbol:id ... bar:bar ...) > #:with value > #'(let ([foo-symbols (set (quote symbol) ...)]) > (list 'foo bar.value ...)))) > > (define-syntax-class bar > #:attributes (value) > (pattern ((~datum bar) symbol:id) > #:with value > #'(list 'bar ???))) > > (syntax-parse stx > [(_ foo:foo ...) > #'(list foo.value ...) ])) > ---------------------------------------------------------------------- > > The problem is what to put in place of the ???. With the split into > two syntax-classes, the expansion of 'bar' no longer has access to > 'foo-symbols'. > > I would need something like syntax-classes that take parameters, but I > didn't find anything like that. Is there some other way to modularize > my definition? Syntax classes can take arguments. Here’s one example, which adds a parameter to bar (which is a syntax object representing a variable bound to the set holding the symbols to check) and passes #’foo-symbols as the argument. (define-syntax (foos-of-bars2 stx) (define-syntax-class (bar symbols-var) #:attributes (value) (pattern ((~datum bar) symbol:id) #:with value #`(list 'bar (if (set-member? #,symbols-var (quote symbol)) (list (quote symbol)) (quote symbol))))) (define-syntax-class foo #:attributes (value) (pattern ((~datum foo) symbol:id ... (~var b (bar #'foo-symbols)) ...) #:with value #'(let ([foo-symbols (set (quote symbol) ...)]) (list 'foo b.value ...)))) (syntax-parse stx [(_ foo:foo ...) #'(list foo.value ...) ])) (foos-of-bars2 (foo x y (bar a) (bar x))) Of course, you can also just to the parameterization at "run time": have the attribute be a function that accepts the set as an argument. The expansion contains obvious beta redexes, which I’m sure the Racket compiler will take care of for you. Here’s the code: (define-syntax (foos-of-bars3 stx) (define-syntax-class foo #:attributes (value) (pattern ((~datum foo) symbol:id ... b:bar ...) #:with value #'(let ([foo-symbols (set (quote symbol) ...)]) (list 'foo (b.fun foo-symbols) ...)))) (define-syntax-class bar #:attributes (fun) (pattern ((~datum bar) symbol:id) #:with fun #'(lambda (symbols-set) (list 'bar (if (set-member? symbols-set (quote symbol)) (list (quote symbol)) (quote symbol)))))) (syntax-parse stx [(_ foo:foo ...) #'(list foo.value ...) ])) (foos-of-bars3 (foo x y (bar a) (bar x))) Ryan ____________________ Racket Users list: http://lists.racket-lang.org/users