Panicz Maciej Godek <godek.mac...@gmail.com> writes: > As a follow-up to the thread > https://lists.gnu.org/archive/html/guile-devel/2015-06/msg00023.html I > announce that I made an update to the (ice-9 nice-9) module. It no > longer re-exports every, any and count, but instead it replaces two > other bindings: > > - define-syntax is now blended with define-syntax-rule, so that if one > writes > > (define-syntax (name . pattern) . substitution) > > the effect will be the same as if she wrote > > (define-syntax name (syntax-rules () ((name . pattern) . > substitution))) > > I think that there's no need to use "define-syntax-rule". > > - let-syntax behaves similarly, i.e. > > (let-syntax (((name . pattern) replacement))) > ....) > > transforms to > > (let-syntax ((name (syntax-rules () ((name . pattern) replacement))) > ....) > > Any comments and suggestions are appreciated. > > Best regards, > M.
Maybe it would be good to make define and define-syntax more symmetric. So if (define (foo . rest) . body) is equivalent to (define foo (lambda rest . body)), then (define-syntax (foo . rest) . body) should perhaps be equivalent to (define-syntax (lambda rest . body)). This is how Racket does it too, and one could say it's the most logical and generalized choice. It has one annoyance, which is that syntax transformers are only ever passed one argument so the ability to use the argument list for something more interesting is diminished, but I wonder if that's really a big deal. I prefer to keep things straightforward and consistent, even if at the expense of forcing a little more verbosity (as long as it's just a little). Also, while it has that annoyance, it also has the advantage of allowing you to do anything you want with that one syntax-object argument you receive, e.g. passing it to syntax-case or (in the future) syntax-parse. OTOH, making the argument list "special" will tie the form to a specific macro system like syntax-rules or syntax-case, and also forbid using multiple pattern/template pairs on it. In my experience, using multiple patterns is very common, and some code-bases also make heavy use of syntax-case instead of syntax-rules, so I wouldn't allocate a primary "syntax slot" like '(define-syntax (...) ...)' to something very specific like "syntax-rules with one arm." What do others think? IMO using 'define-syntax-rule' for the "syntax-rules with one pattern" special case is fine (and already established), so I would say it's better to allocate 'define-syntax' itself to the most generic use-case, like in Racket. --- There are many possible extensions to 'let' (abbrev. for lambda, for let-values, or for match-let), all of which make equally much sense to me, so I think they're all bad, because no matter which one you sanction, you will have discriminated against two others. :-) Just keep pure 'let' pure, and let people specify the exact variant they want... However, for 'let-syntax' the situation is different. There is no let-syntax-values, and there is no match-let-syntax. There is only one way to use let-syntax, which is to bind the identifier to a syntax transformer. So I agree it's a good idea to extend it in that direction. That leaves the question of what sort of syntax transformer should be created, syntax-rules or syntax-case or lambda, and the obvious choice to me is to make it consistent with define-syntax, so in line with my other recommendation, I would make (let-syntax (((foo stx) ...)) ...) equivalent to (let-syntax ((foo (lambda (stx) ...))) ...). And so the widest possible use-cases are covered. Admittedly that slightly discriminates against syntax-rules, which doesn't go well with the implicit lambda. For that reason I would propose a different syntax, similar to define-syntax-rule: (let-syntax-rule (((foo x y) (do stuff)) ((bar a b) (do stuff))) (body goes here)) This way everything is very consistent. Define-syntax and let-syntax are maximally generic and assume no specific macro system so one can dispatch to the system of choice, the exception being syntax-rules which requires there *not* to be a lambda, so for syntax-rules we define the *-syntax-rule variants, and hopefully everyone is happy. --- I also pondered on the following two, but note that each save merely a single trivial line of code per syntax-rules invocation, so I think they have little merit: (define-syntax-rules foo () ((_ x y) (do stuff)) ((_ x y z) (do other stuff))) (let-syntax-rules ((foo () ((_ x y) (do stuff)) ((_ x y z) (do other stuff))) (bar () ((_ a b) (do stuff)) ((_ a b c) (do other stuff)))) (body goes here)) They're highly consistent with the rest though, so it shouldn't hurt adding them if others think it's worth it. --- That amounts to 6 cents, I hope it wasn't excessive. :-P Taylan