# Syntax-rules extensions SKINT implements all standard features of R7RS `syntax-rules`, including custom ellipsis, non-final ellipsis patterns, non-binding underscore pattern, and `(... tpl)` template escapes. It also supports the following extensions: ## Support for boxes Boxes, as defined by SRFI-111 and the future `(scheme box)` library, are supported natively, and can be parts of both patterns and templates. See examples of their use below. ## Simple pattern escape A pattern of the form `( )` where `` is the current ellipsis is interpreted as if it were ``, but ellipses and underscores in `` lose their special meaning; e.g.: ```scheme (define-syntax underscored (syntax-rules () [(_ (... _) (... ...)) (list (... ...) (... _))])) (underscored 1 2) ; => (2 1) ``` Note that R7RS prescribes special treatment of the keyword identifier at the beginning of the pattern in a ``: it is matched automatically with the head of the use form, but is not considered a pattern variable, so can't be substituted. SKINT's pattern escape extension drops this positional restriction and matches its sub-pattern in a normal way; e.g.: ```scheme ; in R7RS, x is not a pattern variable here due to its head position: (let-syntax ([ttt (syntax-rules () [(x y) '(x y)])]) (ttt 123)) ; => (x 123) ; x is a pattern variable here, even though it is in the head position: (let-syntax ([ttt (syntax-rules () [((... x) y) '(x y)])]) (ttt 123)) ; => (ttt 123) ; same thing, but with pattern template escaped via template escape to work properly: ((syntax-rules () ; NB: anonymous transformer positioned at the head of the use form [(_) (let-syntax ([ttt (syntax-rules () [(((... ...) x) y) '(x y)])]) (ttt 123))])) ; => (ttt 123) ``` The importance of this feature will be clear when we get to circumventing hygiene below. ## Named pattern escapes A pattern of the form `( )`, where `` is the current ellipsis, is interpreted as if it were `` as long as the matching S-expression satisfies the constraint specified by ``. The matching fails if the predicate returns `#f`. Predicate names are compared to predefined symbols according to `free-identifier=?` rules. The following named pattern escapes are supported: * `(... number? )` * `(... exact-integer? )` * `(... boolean? )` * `(... char? )` * `(... string? )` * `(... bytevector? )` * `(... id? )` All but the last predicate have the same meaning as the corresponding Scheme procedures. The `id?` predicate checks if the corresponding S-expression is either a symbol or a syntax object representing an identifier. The rationale for adding these escapes is obvious: while `syntax-rules`-based macros can perform very complex calculations with structured S-expressions, they lack an ability to deal with *atomic* S-expressions (with the exception of identifiers – they can be recognized, but the technique for that is quite complicated). Example (also uses box templates): ```scheme (define-syntax wrap-by-type (syntax-rules () [(_ (... string? x)) '#&x] [(_ (... number? x)) '#(x)] [(_ x) 'x])) (list (wrap-by-type 42) (wrap-by-type "yes") (wrap-by-type #\c)) ; => (#(42) #&"yes" #\c) ``` ## Named template escapes A template of the form `( )` where `` is the current ellipsis is interpreted as follows: First, `` (which can be any nonempty sequence of `