Harry Spier wrote: > And if not, would it be possible for someone to give a > simple example of its use.
I will use R6 Scheme here. Scheme defines the IF syntax as: (if ?test ?consequent ?alternate) where the only "language keyword" is IF itself. Many other languages use a version with "then" and "else", which are also "reserved keywords" for those languages; Scheme has no reserved keywords. A Scheme IF with THEN and ELSE, let's call it IF*, would look like: (if ?test (then ?consequent) (else ?alternate)) we can define it with the following simple SYNTAX-RULES: #!r6rs (import (rnrs)) (define-syntax if* (syntax-rules () ((_ ?test (?then ?consequent) (?else ?alternate)) (if ?test ?consequent ?alternate)))) (let ((a 2)) (if* (< 1 a) (then (display "yeah")) (else (display "nay")))) --| yeah but notice that in this definition the pattern is: (_ ?test (?then ?consequent) (?else ?alternate)) and the identifiers ?THEN and ?ELSE become pattern variables, with no validation of their value; so the following macro use also works with no error: (let ((a 2)) (if* (< 1 a) (123 (display "yeah")) (456 (display "nay")))) that is in the template of the first SYNTAX-RULES arm: * the identifier ?THEN is a pattern variable bound to a syntax object holding the number 123; * the identifier ?ELSE is a pattern variable bound to a syntax object holding the number 456; we can verify it with the following modified program: #!r6rs (import (rnrs)) (define-syntax if* (syntax-rules () ((_ ?test (?then ?consequent) (?else ?alternate)) (display ?then)))) (let ((a 2)) (if* (< 1 a) (123 (display "yeah")) (456 (display "nay")))) --| 123 This is not what we want: we would like the macro to verify that the components of the input macro falling in the positions of ?THEN and ?ELSE in the pattern, are identifiers having as names the symbol THEN and the symbol ELSE. Specifically we would like, in those positions, identifiers being FREE-IDENTIFIER=? to "auxiliary keywords" THEN and ELSE that we have defined. We could do such a test using SYNTAX-CASE: #!r6rs (import (except (rnrs) else)) ;; Define auxiliary keywords, they are just identifiers ;; bound to something. (define-syntax then (syntax-rules ())) (define-syntax else (syntax-rules ())) (define-syntax if* (lambda (stx) (syntax-case stx () ((_ ?test (?then ?consequent) (?else ?alternate)) (if (and (identifier? #'?then) (free-identifier=? #'?then #'then)) (display 'good) (display 'bad)))))) (let ((a 2)) (if* (< 1 a) (then (display "yeah")) (else (display "nay")))) --| good (let ((a 2)) (if* (< 1 a) (123 (display "yeah")) (456 (display "nay")))) --| bad We do not need to use SYNTAX-CASE for such a simple validation, because SYNTAX-RULES offers the <LITERAL> arguments exactly for this purpose. So the full version of IF... THEN... ELSE... is: #!r6rs (import (except (rnrs) else)) (define-syntax if* (syntax-rules (then else) ((_ ?test (then ?consequent) (else ?alternate)) (if ?test ?consequent ?alternate)))) (define-syntax then (syntax-rules ())) (define-syntax else (syntax-rules ())) (let ((a 2)) (if* (< 1 a) (then (display "yeah")) (else (display "nay")))) --| yeah (let ((a 2)) (if* (< 1 a) (123 (display "yeah")) (456 (display "nay")))) ---> syntax error The language (rnrs) already defines an auxiliary syntax ELSE and it is all right to use it for IF* so we can just do: #!r6rs (import (rnrs)) (define-syntax if* (syntax-rules (then else) ((_ ?test (then ?consequent) (else ?alternate)) (if ?test ?consequent ?alternate)))) (define-syntax then (syntax-rules ())) Notice that with these definitions we have created actual bindings for THEN and ELSE in the lexical context of the definition for IF*, and IF* will recognise only those. So when writing a library that exports IF* we have to export THEN and ELSE along with it: #!r6rs (library (if-star) (export if* then else) (import (rnrs)) (define-syntax if* (syntax-rules (then else) ((_ ?test (then ?consequent) (else ?alternate)) (if ?test ?consequent ?alternate)))) (define-syntax then (syntax-rules ()))) and use it as: #!r6rs (import (rnrs) (if-star)) (let ((a 2)) (if* (< 1 a) (then (display "yeah")) (else (display "nay")))) --| yeah (let ((a 2)) (if* (< 1 a) (123 (display "yeah")) (456 (display "nay")))) ---> syntax error HTH -- Marco Maggi _________________________________________________ For list-related administrative tasks: http://lists.racket-lang.org/listinfo/users