2015-09-02 16:11 GMT+02:00 Taylan Ulrich Bayırlı/Kammer < taylanbayirli@gmail.com>: > > 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. > > That was my first guess, too, and so initially I did that the way you described, but I eventually concluded that mapping (define-syntax (s . args) . body) as (define-syntax s (syntax-rules () ((s . args) . body))) is more analogous to mapping (define (s . args) . body) as (define s (lambda args . body)) than (define-syntax s (lambda args . template)) This is because, at least in the substitutional model of computation, in both define/lambda and define-syntax/syntax-rules case you can substitute (s values ...) with body where the occurences of args in body are replaced with values. Interpreting (define-syntax (s . args) . body) as (define-syntax s (lambda args . body)) does not work that way, because, as you noted, syntax transformers can take only a single argument, and -- more importantly -- the argument doesn't say anything about how the macro is intended to be used (it is, as Guile manual puts it, "a leaky implementation detail"). I think that syntax-case or syntax-rules with many clauses resembles the use of case-lambda more. > > 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. Not forbid. This is just an extension of syntax that would otherwise be illegal. I agree that it is dubious that the interpretation ties itself to one macro system, but this is the most commonly used macro system in Scheme. I agree that there's an important difference between define-syntax+syntax-rules and define+lambda -- namely, that the former has no intrinsic conditional like "if". 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." > > In my experience it is also very common, but interpreting (define-syntax (name . args) ...) as (define-syntax name (lambda args ...)) doesn't improve readability, and moreover might lead to confusion. (define-syntax s (lambda (stx) (syntax-case stx () ...))) is more explicit than (define-syntax (s stx) (syntax-case stx () ...)) and the former should definitely be preferred over the latter, which would only bring confusion and no improvement whatsoever 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. :-) Well, no, actually there are only two reasonable extensions -- let-values and match-let go together well, so the only one that can be discriminated is the lambda (which would actually discriminate the perfectly-reasonable srfi-71 let variant). And while I don't like the discrepancy between pattern-matching let and syntax-ruling let-syntax, I don't think that interpreting (let (((f x) '(1 2))) ...) as (let ((f (lambda (x) '(1 2)))) ...) could actually be useful. But I do admit that it is only my personal taste&experience. (I actually prefer to introduce internal function definitions using the "define" form) 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. > Well, the define-syntax-rules and let-syntax-rules are non-controversial, and I could even say that I like them a lot (especially let-syntax-rules). My point, however, is to make things controversial, and to pick the right interpretation for the formsthat otherwise wouldn't be legal. So I think that it would be awesome to map (let-syntax ((name keywords pattern . patterns)) body) to (let-syntax ((name (syntax-rules keywords pattern . patterns))) body) (and so forth) > > That amounts to 6 cents, I hope it wasn't excessive. :-P > I only have a dollar: $