mirror of
https://github.com/ashinn/chibi-scheme.git
synced 2025-05-20 06:09:18 +02:00
188 lines
No EOL
19 KiB
HTML
Executable file
188 lines
No EOL
19 KiB
HTML
Executable file
<html><head><title>(chibi match)</title>
|
|
<style type="text/css">
|
|
body {color: #000; background-color: #FFF}
|
|
div#menu {font-size: smaller; position: absolute; top: 50px; left: 0; width: 180px; height: 100%}
|
|
div#main {position: absolute; top: 0; left: 200px; width: 520px; height: 100%}
|
|
div#notes {position: relative; top: 2em; left: 550px; max-width: 200px; height: 0px; font-size: smaller;}
|
|
div#footer {padding-bottom: 50px}
|
|
.result { color: #000; background-color: #FFEADF; width: 100%; padding: 3px}
|
|
.command { color: #000; background-color: #FFEADF; width: 100%; padding: 5px}
|
|
.keyword { color: #800080; background-color: inherit; }
|
|
.type { color: #008000; background-color: inherit; }
|
|
.function { color: #0000FF; background-color: inherit; }
|
|
.variable { color: #B8860B; background-color: inherit; }
|
|
.comment { color: #FF0000; background-color: inherit; }
|
|
.string { color: #BC8F8F; background-color: inherit; }
|
|
.attribute { color: #FF5000; background-color: inherit; }
|
|
.preprocessor { color: #FF00FF; background-color: inherit; }
|
|
.builtin { color: #FF00FF; background-color: inherit; }
|
|
.character { color: #0055AA; background-color: inherit; }
|
|
.syntaxerror { color: #FF0000; background-color: inherit; }
|
|
.diff-deleted { color: #5F2121; background-color: inherit; }
|
|
.diff-added { color: #215F21; background-color: inherit; }
|
|
span.paren1 { color: #AAAAAA; background-color: inherit; }
|
|
span.paren2 { color: #888888; background-color: inherit; }
|
|
span.paren3 { color: #666666; background-color: inherit; }
|
|
span.paren4 { color: #444444; background-color: inherit; }
|
|
span.paren5 { color: #222222; background-color: inherit; }
|
|
span.paren6 { color: #000000; background-color: inherit; }
|
|
</style>
|
|
</head><body><div id="menu"><ol><li><a href="#h3_Patterns">Patterns</a></li><li><a href="#h3_Syntax">Syntax</a><ol><li><a href="#h4_(matchexpr(pattern.body)...)(matchexpr(pattern(=>failure).body)...)">(match expr (pattern . body) ...)
|
|
(match expr (pattern (=> failure) . body) ...)</a></li><li><a href="#h4_match-lambda">(match-lambda (pattern . body) ...)</a></li><li><a href="#h4_match-lambda*">(match-lambda* (pattern . body) ...)</a></li><li><a href="#h4_match-let">(match-let ((var value) ...) . body)(match-let loop ((var init) ...) . body)</a></li><li><a href="#h4_match-letrec">(match-letrec ((var value) ...) . body)</a></li><li><a href="#h4_(match-let*((varvalue)...)body...)">(match-let* ((var value) ...) body ...)</a></li></ol></li></ol></div><div id="main"><h1>(chibi match)</h1><p>
|
|
This is a full superset of the popular <a href="http://www.cs.indiana.edu/scheme-repository/code.match.html">match</a>
|
|
package by Andrew Wright, written in fully portable <code><span>syntax-rules</span></code>
|
|
and thus preserving hygiene.
|
|
The most notable extensions are the ability to use <em>non-linear</em>
|
|
patterns - patterns in which the same identifier occurs multiple
|
|
times, tail patterns after ellipsis, and the experimental tree patterns.
|
|
</p><div><a name="h3_Patterns"></a><h3>Patterns</h3></div><p>
|
|
Patterns are written to look like the printed representation of
|
|
the objects they match. The basic usage is
|
|
<code>(<span class="keyword">match</span> <span>expr</span> (pat <span>body</span> <span>...</span>) <span>...</span>)</code>
|
|
where the result of <code>expr</code> is matched against each pattern in
|
|
turn, and the corresponding body is evaluated for the first to
|
|
succeed. Thus, a list of three elements matches a list of three
|
|
elements.
|
|
</p><div><pre><code>(<span class="keyword">let</span> ((ls (list <span>1</span> <span>2</span> <span>3</span>))) (<span class="keyword">match</span> <span>ls</span> ((1 <span>2</span> <span>3</span>) #t)))</code></pre><code><div class="result">=> #t</div></code></div><p>
|
|
If no patterns match an error is signalled.
|
|
Identifiers will match anything, and make the corresponding
|
|
binding available in the body.
|
|
</p><div><pre><code>(<span class="keyword">match</span> (list <span>1</span> <span>2</span> <span>3</span>) ((a <span>b</span> <span>c</span>) <span>b</span>))</code></pre><code><div class="result">=> 2</div></code></div><p>
|
|
If the same identifier occurs multiple times, the first instance
|
|
will match anything, but subsequent instances must match a value
|
|
which is <code><span>equal?</span></code> to the first.
|
|
</p><div><pre><code>(<span class="keyword">match</span> (list <span>1</span> <span>2</span> <span>1</span>) ((a <span>a</span> <span>b</span>) <span>1</span>) ((a <span>b</span> <span>a</span>) <span>2</span>))</code></pre><code><div class="result">=> 2</div></code></div><p>
|
|
The special identifier <code><span>_</span></code> matches anything, no matter how
|
|
many times it is used, and does not bind the result in the body.
|
|
</p><div><pre><code>(<span class="keyword">match</span> (list <span>1</span> <span>2</span> <span>1</span>) ((_ <span>_</span> <span>b</span>) <span>1</span>) ((a <span>b</span> <span>a</span>) <span>2</span>))</code></pre><code><div class="result">=> 1</div></code></div><p>
|
|
To match a literal identifier (or list or any other literal), use
|
|
<code><span>quote</span></code>.
|
|
</p><div><pre><code>(<span class="keyword">match</span> '<span>a</span> ('<span>b</span> <span>1</span>) ('<span>a</span> <span>2</span>))</code></pre><code><div class="result">=> 2</div></code></div><p>
|
|
Analogous to its normal usage in scheme, <code><span>quasiquote</span></code> can
|
|
be used to quote a mostly literally matching object with selected
|
|
parts unquoted.
|
|
</p><div><pre><code>(<span class="keyword">match</span> (list <span>1</span> <span>2</span> <span>3</span>) (`(1 ,<span>b</span> ,<span>c</span>) (list <span>b</span> <span>c</span>)))</code></pre><code><div class="result">=> (2 3)</div></code></div><p>
|
|
Often you want to match any number of a repeated pattern. Inside
|
|
a list pattern you can append <code><span>...</span></code> after an element to
|
|
match zero or more of that pattern (like a regexp Kleene star).
|
|
</p><div><pre><code>(<span class="keyword">match</span> (list <span>1</span> <span>2</span>) ((1 <span>2</span> <span>3</span> <span>...</span>) #t))</code></pre><code><div class="result">=> #t</div></code></div><p>
|
|
</p><div><pre><code>(<span class="keyword">match</span> (list <span>1</span> <span>2</span> <span>3</span>) ((1 <span>2</span> <span>3</span> <span>...</span>) #t))</code></pre><code><div class="result">=> #t</div></code></div><p>
|
|
</p><div><pre><code>(<span class="keyword">match</span> (list <span>1</span> <span>2</span> <span>3</span> <span>3</span> <span>3</span>) ((1 <span>2</span> <span>3</span> <span>...</span>) #t))</code></pre><code><div class="result">=> #t</div></code></div><p>
|
|
Pattern variables matched inside the repeated pattern are bound to
|
|
a list of each matching instance in the body.
|
|
</p><div><pre><code>(<span class="keyword">match</span> (list <span>1</span> <span>2</span>) ((a <span>b</span> <span>c</span> <span>...</span>) <span>c</span>))</code></pre><code><div class="result">=> ()</div></code></div><p>
|
|
</p><div><pre><code>(<span class="keyword">match</span> (list <span>1</span> <span>2</span> <span>3</span>) ((a <span>b</span> <span>c</span> <span>...</span>) <span>c</span>))</code></pre><code><div class="result">=> (3)</div></code></div><p>
|
|
</p><div><pre><code>(<span class="keyword">match</span> (list <span>1</span> <span>2</span> <span>3</span> <span>4</span> <span>5</span>) ((a <span>b</span> <span>c</span> <span>...</span>) <span>c</span>))</code></pre><code><div class="result">=> (3 4 5)</div></code></div><p>
|
|
More than one <code><span>...</span></code> may not be used in the same list, since
|
|
this would require exponential backtracking in the general case.
|
|
However, <code><span>...</span></code> need not be the final element in the list,
|
|
and may be succeeded by a fixed number of patterns.
|
|
</p><div><pre><code>(<span class="keyword">match</span> (list <span>1</span> <span>2</span> <span>3</span> <span>4</span>) ((a <span>b</span> <span>c</span> <span>...</span> <span>d</span> <span>e</span>) <span>c</span>))</code></pre><code><div class="result">=> ()</div></code></div><p>
|
|
</p><div><pre><code>(<span class="keyword">match</span> (list <span>1</span> <span>2</span> <span>3</span> <span>4</span> <span>5</span>) ((a <span>b</span> <span>c</span> <span>...</span> <span>d</span> <span>e</span>) <span>c</span>))</code></pre><code><div class="result">=> (3)</div></code></div><p>
|
|
</p><div><pre><code>(<span class="keyword">match</span> (list <span>1</span> <span>2</span> <span>3</span> <span>4</span> <span>5</span> <span>6</span> <span>7</span>) ((a <span>b</span> <span>c</span> <span>...</span> <span>d</span> <span>e</span>) <span>c</span>))</code></pre><code><div class="result">=> (3 4 5)</div></code></div><p>
|
|
<code><span>___</span></code> is provided as an alias for <code><span>...</span></code> when it is
|
|
inconvenient to use the ellipsis (as in a syntax-rules template).
|
|
The <code><span>..1</span></code> syntax is exactly like the <code><span>...</span></code> except
|
|
that it matches one or more repetitions (like a regexp "+").
|
|
</p><div><pre><code>(<span class="keyword">match</span> (list <span>1</span> <span>2</span>) ((a <span>b</span> <span>c</span> <span>..1</span>) <span>c</span>))</code></pre><code><div class="result">ERROR: match: "no matching pattern"
|
|
</div></code></div><p>
|
|
</p><div><pre><code>(<span class="keyword">match</span> (list <span>1</span> <span>2</span> <span>3</span>) ((a <span>b</span> <span>c</span> <span>..1</span>) <span>c</span>))</code></pre><code><div class="result">=> (3)</div></code></div><p>
|
|
The boolean operators <code><span>and</span></code>, <code><span>or</span></code> and <code><span>not</span></code>
|
|
can be used to group and negate patterns analogously to their
|
|
Scheme counterparts.
|
|
The <code><span>and</span></code> operator ensures that all subpatterns match.
|
|
This operator is often used with the idiom <code>(and <span>x</span> <span>pat</span>)</code> to
|
|
bind <code>x</code> to the entire value that matches <code>pat</code>
|
|
(c.f. "as-patterns" in ML or Haskell). Another common use is in
|
|
conjunction with <code><span>not</span></code> patterns to match a general case
|
|
with certain exceptions.
|
|
</p><div><pre><code>(<span class="keyword">match</span> <span>1</span> ((and) #t))</code></pre><code><div class="result">=> #t</div></code></div><p>
|
|
</p><div><pre><code>(<span class="keyword">match</span> <span>1</span> ((and <span>x</span>) <span>x</span>))</code></pre><code><div class="result">=> 1</div></code></div><p>
|
|
</p><div><pre><code>(<span class="keyword">match</span> <span>1</span> ((and <span>x</span> <span>1</span>) <span>x</span>))</code></pre><code><div class="result">=> 1</div></code></div><p>
|
|
The <code><span>or</span></code> operator ensures that at least one subpattern
|
|
matches. If the same identifier occurs in different subpatterns,
|
|
it is matched independently. All identifiers from all subpatterns
|
|
are bound if the <code><span>or</span></code> operator matches, but the binding is
|
|
only defined for identifiers from the subpattern which matched.
|
|
</p><div><pre><code>(<span class="keyword">match</span> <span>1</span> ((or) #t) (<span class="keyword">else</span> #f))</code></pre><code><div class="result">=> #f</div></code></div><p>
|
|
</p><div><pre><code>(<span class="keyword">match</span> <span>1</span> ((or <span>x</span>) <span>x</span>))</code></pre><code><div class="result">=> 1</div></code></div><p>
|
|
</p><div><pre><code>(<span class="keyword">match</span> <span>1</span> ((or <span>x</span> <span>2</span>) <span>x</span>))</code></pre><code><div class="result">=> 1</div></code></div><p>
|
|
The <code><span>not</span></code> operator succeeds if the given pattern doesn't
|
|
match. None of the identifiers used are available in the body.
|
|
</p><div><pre><code>(<span class="keyword">match</span> <span>1</span> ((not <span>2</span>) #t))</code></pre><code><div class="result">=> #t</div></code></div><p>
|
|
The more general operator <code><span>?</span></code> can be used to provide a
|
|
predicate. The usage is <code>(? <span>predicate</span> <span>pat</span> <span>...</span>)</code> where
|
|
<code>predicate</code> is a Scheme expression evaluating to a predicate
|
|
called on the value to match, and any optional patterns after the
|
|
predicate are then matched as in an <code><span>and</span></code> pattern.
|
|
</p><div><pre><code>(<span class="keyword">match</span> <span>1</span> ((? <span>odd?</span> <span>x</span>) <span>x</span>))</code></pre><code><div class="result">=> 1</div></code></div><p>
|
|
The field operator <code><span>=</span></code> is used to extract an arbitrary
|
|
field and match against it. It is useful for more complex or
|
|
conditional destructuring that can't be more directly expressed in
|
|
the pattern syntax. The usage is <code>(= <span>field</span> <span>pat</span>)</code>, where
|
|
<code>field</code> can be any expression, and should result in a
|
|
procedure of one argument, which is applied to the value to match
|
|
to generate a new value to match against <code>pat</code>.
|
|
Thus the pattern <code>(and (= <span>car</span> <span>x</span>) (= <span>cdr</span> <span>y</span>))</code> is equivalent
|
|
to <code>(x <span>.</span> <span>y</span>)</code>, except it will result in an immediate error
|
|
if the value isn't a pair.
|
|
</p><div><pre><code>(<span class="keyword">match</span> '(1 <span>.</span> <span>2</span>) ((= <span>car</span> <span>x</span>) <span>x</span>))</code></pre><code><div class="result">=> 1</div></code></div><p>
|
|
</p><div><pre><code>(<span class="keyword">match</span> <span>4</span> ((= <span>sqrt</span> <span>x</span>) <span>x</span>))</code></pre><code><div class="result">=> 2</div></code></div><p>
|
|
The record operator <code><span>$</span></code> is used as a concise way to match
|
|
records defined by SRFI-9 (or SRFI-99). The usage is
|
|
<code>($ <span>rtd</span> <span>field</span> <span>...</span>)</code>, where <code>rtd</code> should be the record
|
|
type descriptor specified as the first argument to
|
|
<code><span>define-record-type</span></code>, and each <code>field</code> is a subpattern
|
|
matched against the fields of the record in order. Not all fields
|
|
must be present.
|
|
</p><div><pre><code>(<span class="keyword">let</span> ()
|
|
(<span class="keyword">define-record-type</span> <span class="function">employee</span>
|
|
(make-employee <span>name</span> <span>title</span>)
|
|
<span>employee?</span>
|
|
(name <span>get-name</span>)
|
|
(title <span>get-title</span>))
|
|
(<span class="keyword">match</span> (make-employee <span class="string">"Bob"</span> <span class="string">"Doctor"</span>)
|
|
(($ <span>employee</span> <span>n</span> <span>t</span>) (list <span>t</span> <span>n</span>))))
|
|
</code></pre><code><div class="result">=> ("Doctor" "Bob")</div></code></div><p>
|
|
The <code><span>set!</span></code> and <code><span>get!</span></code> operators are used to bind an
|
|
identifier to the setter and getter of a field, respectively. The
|
|
setter is a procedure of one argument, which mutates the field to
|
|
that argument. The getter is a procedure of no arguments which
|
|
returns the current value of the field.
|
|
</p><div><pre><code>(<span class="keyword">let</span> ((x (cons <span>1</span> <span>2</span>))) (<span class="keyword">match</span> <span>x</span> ((1 <span>.</span> (<span class="keyword">set!</span> <span>s</span>)) (s <span>3</span>) <span>x</span>)))</code></pre><code><div class="result">=> (1 . 3)</div></code></div><p>
|
|
</p><div><pre><code>(<span class="keyword">match</span> '(1 <span>.</span> <span>2</span>) ((1 <span>.</span> (get! <span>g</span>)) (g)))</code></pre><code><div class="result">=> 2</div></code></div><p>
|
|
The new operator <code><span>***</span></code> can be used to search a tree for
|
|
subpatterns. A pattern of the form <code>(x <span>***</span> <span>y</span>)</code> represents
|
|
the subpattern <code>y</code> located somewhere in a tree where the path
|
|
from the current object to <code>y</code> can be seen as a list of the
|
|
form <code>(x <span>...</span>)</code>. <code>y</code> can immediately match the current
|
|
object in which case the path is the empty list. In a sense it's
|
|
a 2-dimensional version of the <code><span>...</span></code> pattern.
|
|
As a common case the pattern <code>(_ <span>***</span> <span>y</span>)</code> can be used to
|
|
search for <code>y</code> anywhere in a tree, regardless of the path
|
|
used.
|
|
</p><div><pre><code>(<span class="keyword">match</span> '(a (a (a <span>b</span>))) ((x <span>***</span> '<span>b</span>) <span>x</span>))</code></pre><code><div class="result">=> (a a a)</div></code></div><p>
|
|
</p><div><pre><code>(<span class="keyword">match</span> '(a (b) (c (d <span>e</span>) (f <span>g</span>))) ((x <span>***</span> '<span>g</span>) <span>x</span>))</code></pre><code><div class="result">=> (a c f)</div></code></div><div><a name="h3_Syntax"></a><h3>Syntax</h3></div><p>
|
|
</p><div><a name="h4_(matchexpr(pattern.body)...)(matchexpr(pattern(=>failure).body)...)"></a><h4><code>(match expr (pattern . body) ...)<br></br>
|
|
(match expr (pattern (=> failure) . body) ...)</code></h4></div><p>
|
|
The result of <code>expr</code> is matched against each <code>pattern</code> in
|
|
turn, according to the pattern rules described in the previous
|
|
section, until the the first <code>pattern</code> matches. When a match is
|
|
found, the corresponding <code>body</code>s are evaluated in order,
|
|
and the result of the last expression is returned as the result
|
|
of the entire <code><span>match</span></code>. If a <code>failure</code> is provided,
|
|
then it is bound to a procedure of no arguments which continues,
|
|
processing at the next <code>pattern</code>. If no <code>pattern</code> matches,
|
|
an error is signalled.</p><div><a name="h4_match-lambda"></a><h4><code>(match-lambda (pattern . body) ...)</code></h4></div><p>Shortcut for <code><span>lambda</span></code> + <code><span>match</span></code>. Creates a
|
|
procedure of one argument, and matches that argument against each
|
|
clause.</p><div><a name="h4_match-lambda*"></a><h4><code>(match-lambda* (pattern . body) ...)</code></h4></div><p>Similar to <code><span>match-lambda</span></code>. Creates a procedure of any
|
|
number of arguments, and matches the argument list against each
|
|
clause.</p><div><a name="h4_match-let"></a><h4><code>(match-let ((var value) ...) . body)<br></br>(match-let loop ((var init) ...) . body)</code></h4></div><p>Matches each var to the corresponding expression, and evaluates
|
|
the body with all match variables in scope. Raises an error if
|
|
any of the expressions fail to match. Syntax analogous to named
|
|
let can also be used for recursive functions which match on their
|
|
arguments as in <code><span>match-lambda*</span></code>.</p><div><a name="h4_match-letrec"></a><h4><code>(match-letrec ((var value) ...) . body)</code></h4></div><p>Similar to <code><span>match-let</span></code>, but analogously to <code><span>letrec</span></code>
|
|
matches and binds the variables with all match variables in scope.</p><div><a name="h4_(match-let*((varvalue)...)body...)"></a><h4><code>(match-let* ((var value) ...) body ...)</code></h4></div><p>
|
|
Similar to <code><span>match-let</span></code>, but analogously to <code><span>let*</span></code>
|
|
matches and binds the variables in sequence, with preceding match
|
|
variables in scope.</p><div id="footer"></div></div></body></html> |