Le mercredi 18 janvier 2017 00:02:17 UTC+1, Alexis King a écrit : > > It’s no secret that I love syntax/parse, but I’m a little less vocal > of my love of syntax/parse/experimental/template, mostly because > of that scary “experimental” in the name. Really, though, template > is great, and it’s to syntax what syntax-parse is to syntax-case.
I'm using it a lot too, and it works fine, so I'm voting to pull it out of experimental too. I'll shamelessly point to my small PR https://github.com/racket/racket/pull/1514 which adds syntax-local-template-metafunction-introduce, and would be nice to include in the non-experimental version. I have been wanting for a while to implement a way to escape syntax templates (for now those from syntax/parse/experimental/template), and have the escaped code be iterated over if it is under an ellipsis, and now seems a good time to do this as it would require some changes in syntax/parse/template. Here is a simplistic example: (syntax-case #'(1 2 3) [(x ...) (template (#,(* (syntax-e #'x) 2) ...))]) ;; => #'(2 4 6) There are a couple of issues to address: - Within the #,escaped form, syntax pattern variables should have a nesting level one less than their outer nesting level. - The (template) form should be able to know which syntax pattern variables are referred to by the fully-expanded #,escaped form, to know which ones to iterate over (and to actually perform the iteration at run-time). The problem is that these informations depend on each other: - Within the #,escaped form, the identifier x should be shadowed with a less nested syntax pattern variable, and this needs to be done before expanding the #,escaped form, as nested uses of syntax or template need to know the correct depth - The (template) form needs to fully-expand the #,escaped form in order to know which syntax pattern variables are referenced within. I'm not sure how to solve this predicament. - I thought about modifying syntax-mapping-depth in racket/private/sc to subtract an “outer depth” stored in a make-parameter, but then the run-time value of the variable pointed to by syntax-mapping-valvar would not be correct. Another run-time make-parameter could store the "current path", so that syntax-mapping-valvar returns that subpart, but this starts to feel like piling hacks on top of each other. - Another solution is to change syntax and template to cooperate, with a similar use of make-parameter. A quick search for syntax-mapping-depth on GitHub showed only these two forms, in various forks of the official Racket repository, so I think it's reasonably safe to change those instead. - A third solution would be to change syntax-case and syntax-parse to record all identifiers bound as syntax pattern variables. It would then be possible to preemptively shadow all of those (somewhat costly, but this allows many improvements and modifications of template, for example I have written a subtemplate macro which automatically calls generate-temporaries to create yᵢ ... identifiers if there is a syntax pattern variable under ellipses named xᵢ, and the current implementation relies on a boatload of heuristics to find the "original" syntax pattern variable). I'm also concerned about the performance implications of changing such a low-level mechanism in Racket. Even if the change to syntax-mapping-depth and syntax-mapping-valvar, syntax and template, or syntax-case and syntax-parse is as simple as checking the value of a parameter, these are used everywhere. I'm open to any suggestion! -- You received this message because you are subscribed to the Google Groups "Racket Developers" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. To post to this group, send email to [email protected]. To view this discussion on the web visit https://groups.google.com/d/msgid/racket-dev/a3ff198e-a937-4b1c-8966-4550333ab665%40googlegroups.com. For more options, visit https://groups.google.com/d/optout.
