Overview
Pattern matching on syntax objects for macro transformers.
(import (std syntax-match))
(def/macro (my-let form inject compare)
(syntax-match form
((_ ((name value) ...) body ...)
#'((fun (,@name) ,@body) ,@value))
(bad (syntax-error bad "my-let takes a binding list and a body."))))
#' constructs syntax and syntax-match destructures it. Use
this macro instead of raw match on Syntax records.
A syntax-match form compiles into a single pattern match.
Each clause becomes a pattern branch. Structural tests become pattern guards
(#:when). Ellipses over compound patterns desugar into folds using
all-of. See Docs/MACROS.org for comprehensive macro documentation.
See also: syntax-match, all-of
Reference
Functions
all-of
function ↑ Functions
(: all-of (-> (List %a) (-> %a (Option %b)) (Option (List %b))))
(all-of items f)
Applies a function across a list, returning all results or None if any element fails.
items- The list of items to process.
f- Transformation function returning (Some transformed) or None on failure.
- returns
- (Some results) in original order if f succeeds for every element, otherwise None.
(all-of (list 1 2 3) (fun (n) (if (> n 0) (Some (* n 2)) None))) ; (Some (list 2 4 6))
(all-of (list 1 -2 3) (fun (n) (if (> n 0) (Some n) None))) ; None
Used by syntax-match when expanding ellipses over compound
patterns, such as ((name value) ...). Short-circuits on the first
failure. Returns (Some (list)) for empty input.
See also: syntax-match
Macros
syntax-match
macro ↑ Macros
(syntax-match subject clause ...)
Matches a syntax expression against structural patterns, executing the first matching clause.
subject- Syntax expression to inspect, typically the macro input form.
clause ...- Clause specification
(pattern body ...). Pattern variables are scoped within the clause body. The final expression determines the clause value.
(def/macro (swap! form inject compare)
(syntax-match form
((_ a b)
#'(let ((tmp ,a)) (set! ,a ,b) (set! ,b tmp)))
(bad (syntax-error bad "swap! takes two variables: (swap! a b)."))))
;; 'else matches the identifier else; a keyword matches that keyword
(syntax-match clause
(('else body ...) #'(begin ,@body))
((#:when test body ...) #'(when ,test ,@body))
((test body ...) #'(if ,test (begin ,@body) unit)))
Supported pattern forms:
_: Wildcard pattern; matches any syntax without binding.
name: Variable pattern; matches any syntax and binds it to name.
Variable names must start with a lowercase letter. Uppercase names cause
compile errors because they resemble union constructors; use quoted literals
like 'Cons to match capitalized identifiers.
'name: Identifier literal; matches identifier name using
syntax-ident=? (ignoring hygiene marks).
Literals: Integers, strings, characters, and keywords match exact literal values.
(p q): Fixed-length list pattern matching each sub-pattern positionally.
(p q ...): Variable-length pattern requiring initial matches for
prefixes, with trailing elements matching q. If q is a variable,
it binds remaining items as (List Syntax). If q is a compound
pattern, inner variables bind lists of matched elements. Ellipses may nest:
((head arg ...) ...) binds head to a list and arg to a
list of lists.
Restrictions: Only one ... is allowed per list pattern, and it must
appear at the end. Duplicate variable bindings within a pattern are syntax
errors.
Clauses evaluate in declaration order. If no clauses match and no
wildcard/catch-all clause is present, a compile error is raised indicating
that no clause matched. Provide a final fallback clause like
(bad (syntax-error bad "...")) to generate informative macro errors.
See also: all-of