matching.lsp
Module: matching
Author: Jeff Ober
Version: 1.0
Original location: http://static.artfulcode.net/newlisp/matching.lsp
Source: http.lsp
Package definition: matching.qwerty
Complex conditionals using match and unify (updated for newlisp 10)
Matching conditionals make possible a very terse style of programming common to the ML family of languages.
Version history
1.0 • updated for newlisp 10 • renamed module to matching • removed dependency on util.lsp • made match-bind a global symbol • fixed error in documentation for match-cond • fixed error in match-cond that bound arguments incorrectly • removed match-with and if-match because they were generally confusing and unnecessary • match-bind no longer binds exact matches (e.g. 'foo and 'foo), only wildcards • fixed bug in match-case where target was bound incorrectly in some cases
0.5 • fixed bug in with-match causing $0 to be misinterpreted in certain circumstances
0.4 • added with-match, a simpler operator that is more idiomatic of newLISP
0.3 • added if-match, match-with
0.2 • altered argument order in match-cond • added match-case
0.1 • initial release • added match-bind, match-let- § -
match-bind
syntax: (match-bind vars pattern target)
parameter: vars - symbols to bind
parameter: pattern - match pattern
parameter: target - match target
If (match pattern target) is valid, binds vars to the result of its evaluation.
example:(match-bind '(a b) '(? ?) '(1 2)) a => 1 b => 2- § -
match-let
syntax: (match-let (vars pattern target) body ...)
parameter: vars - symbols to bind
parameter: pattern - match pattern
parameter: target - match target
parameter: body - series of forms to be evaluated
match-let will evaluate body in an environment where variables vars are bound to the destructured values from target according to match pattern pattern. Thus, if the result of (match pattern target) is (1 2 (3 4)), vars (a b c) will be bound as ((a 1) (b 2) (c '(3 4))).
Should pattern not match target, an error is signaled. Note that target is evaluated before body is executed. target is evaluated even if the match fails, as it is the evaluated form against which pattern is matched.
example:(let ((lst '(1 2 3 4))) (match-let ((a b c) (? ? *) lst) (+ a b (apply * c)))) => 15- § -
match-case
syntax: (match-case target (case-pattern case-vars case-expr) ...)
parameter: target - the expression to match against
parameter: case-pattern - the pattern to match with target
parameter: case-vars - the symbols to bind to the result of the match
parameter: case-expr - the form to be evaluated should case-pattern match successfully
match-case tries a series of match cases in sequence and returns the result of evaluating the first successful match's case-expr in a local scope in which symbols case-vars are bound to the result of matching case-pattern against target.
example:(let ((x '(1 2 3 4 5))) (match-case x ((? ? ?) (a b c) (println "this form is not evaluated since '(? ? ?) does not match x")) ((? ? *) (a b c) (println "c is bound to " c " in this form")) ((*) (a) (println "catch-all")))) ; (*) matches all lists, so it is catch-all for x => "c is bound to (3 4 5) in this form"- § -
match-cond
syntax: (match-cond ((pattern vars target) body-forms) ...)
parameter: pattern - match pattern
parameter: vars - symbols to bind
parameter: target - match target
parameter: body - series of forms to be evaluated
match-cond evaluates a series of match/bind combinations until one of them evaluates non-nil. The result of the successful match will be bound to the symbols in vars, and the associated body-forms will be evaluated with those symbols locally bound. The result of the evaluation is nil if no forms match or the result of the final body-form evaluated.
match-cond is more versatile than match-case in that match-cond may test against multiple targets and evaluates its body-forms in an implicit begin block.
example:(let ((x '(1 2 3 4 5))) (match-cond (((? ? ?) (a b c) x) (println "evaluation never gets here")) (((? ? *) (a b c) x) (println "c gets bound to " c)) (((*) (a) x) (println "catch-all")))) ; (*) matches all lists, so is catch-all for x => "c gets bound to (3 4 5)"- § -
with-match
syntax: (with-match target (match-form-n body-n) ...)
parameter: target - target of the match
parameter: match-expr-n - match pattern to be tested against target
parameter: body-n - block to be evaluated if match-expr-n matches successfully
Tests each match-expr-n in turn against target. On the first successful match, the system variable $0 is bound to the result of the match and the paired body-n is evaluated. No further match forms are tested after a successful match and the result of the evaluation of body-n is returned. If no match is successful, nil is returned.
example:(with-match '(1 2 3 (4 5)) ((? ? ? (? ?)) (apply + $0)) ((? *) (println "Never gets here"))) => 15- ∂ -
Artful Code
generated with newLISP and newLISPdoc