This is the mail archive of the kawa@sourceware.org mailing list for the Kawa project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

match form as a generalization of case


I checked into the invoke branch a new 'match' form.
(Actually, it was there before, but was broken.)
I also checked some pattern extension to make match more useful, and
documentation.

If you want to try it out without re-building form git,
you can try this:
http://ftp.gnu.org/gnu/kawa/kawa-2.91_invoke-20170121.zip

That zip file includes the documentation, which you can browse
with the command:
  kawa-2.91_invoke/bin/kawa --browse-manual

Here are the highlights.  Note also that lambda and let forms
both take PATTERNs now.

 -- Syntax: match MATCH-KEY EXPRESSION MATCH-CLAUSE^{+}
     The ‘match’ form is a generalization of ‘case’ using PATTERNs,
          MATCH-KEY ::= EXPRESSION
          MATCH-CLAUSE ::=
            ‘(’ PATTERN [GUARD] BODY ‘)’
     The MATCH-KEY is evaluated, Then the MATCH-CLAUSEs are tried in
     order.  The first MATCH-CLAUSE whose PATTERN matches (and the
     GUARD, if any, is true), is selected, and the corresponding BODY
     evaluated.  It is an error if no MATCH-CLAUSE matches.
          (match value
            (0 (found-zero))
            (x #if (> x 0) (found-positive x))
            (x #if (< x 0) (found-negative x))
            (x::symbol (found-symbol x))
            (_ (found-other)))

     One ‘case’ feature is not (yet) directly supported by ‘match’:
     Matching against a list of values.  However, this is easy to
     simulate using a guard using ‘memq’, ‘memv’, or ‘member’:
          ;; compare similar example under case
          (match (car '(c d))
            (x #!if (memv x '(a e i o u)) ’vowel)
            (x #!if (memv x '(w y)) ’semivowel)
            (x x))

8.3.1 Patterns
--------------

The usual way to bind variables is to match an incoming value against a
“pattern”.  The pattern contains variables that are bound to some value
derived from the value.
     (! [x::double y::double] (some-expression))
In the above example, the pattern ‘[x::double y::double]’ is matched
against the incoming value that results from evaluating
‘(some-expression)’.  That value is required to be a two-element
sequence.  Then the sub-pattern ‘x::double’ is matched against element 0
of the sequence, which means it is coerced to a ‘double’ and then the
coerced value is matched against the sub-pattern ‘x’ (which trivially
succeeds).  Similarly, ‘y::double’ is matched against element 1.

The syntax of patterns is a work-in-progress.  (The focus until now has
been in designing and implementing how patterns work in general, rather
than the details of the pattern syntax.)

     PATTERN ::= IDENTIFIER
       | ‘_’
       | PATTERN-LITERAL
       | ‘’’DATUM
       | PATTERN ‘::’ TYPE
       | ‘[’ LPATTERN^{*} ‘]’
     LPATTERN ::= PATTERN
       | ‘@’ PATTERN
       | PATTERN ‘...’
       | GUARD
     PATTERN-LITERAL ::=
         BOOLEAN | number | CHARACTER | STRING
     GUARD ::= ‘#!if’ EXPRESSION

This is how the specific patterns work:

IDENTIFIER
     This is the simplest and most common form of pattern.  The
     IDENTIFIER is bound to a new variable that is initialized to the
     incoming value.

‘_’
     This pattern just discards the incoming value.  It is equivalent to
     a unique otherwise-unused IDENTIFIER.

PATTERN-LITERAL
     Matches if the value is ‘equal?’ to the PATTERN-LITERAL.

‘’’DATUM
     Matches if the value is ‘equal?’ to the quoted DATUM.

PATTERN ‘::’ TYPE
     The incoming value is coerced to a value of the specified TYPE, and
     then the coerced value is matched against the sub-PATTERN.  Most
     commonly the sub-PATTERN is a plain IDENTIFIER, so the latter match
     is trivial.

‘[’ LPATTERN^{*} ‘]’
     The incoming value must be a sequence (a list, vector or similar).
     In the case where each sub-pattern is a plain PATTERN, then the
     number of sub-patterns must match the size of the sequence, and
     each sub-pattern is matched against the corresponding element of
     the sequence.  More generally, each sub-pattern may match zero or
     more consequtive elements of the incoming sequence.

‘#!if’ EXPRESSION
     No incoming value is used.  Instead the EXPRESSION is evaluated.
     If the result is true, matching succeeds (so far); otherwise the
     match fails.  This form is called a “guard”
     (https://en.wikipedia.org/wiki/Guard_(computer_science)).

--
	--Per Bothner
per@bothner.com   http://per.bothner.com/


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]