Skip to content

bjornkihlberg/chezscheme-match

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

43 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

chezscheme-match

Pattern matching in Chez Scheme


Quickstart

Pattern match syntax

(match value clause*)

Where value is an eagerly evaluated expression and clause is described with the following grammar:

<clause>
  ::= (pattern guard-clause expression*)
    | (pattern expression*)

<guard-clause>
  ::= (? expression)

<pattern>
  ::= symbol                        ; Variable binding, eg x, y or z
    | literal                       ; Literal, eg "hello", 5 or '(huey dewey louie)
    | (& pattern pattern pattern*)  ; Multiple patterns on same value
    | (-> expression pattern)       ; Apply value to <expression> and match <pattern> on result
                                    ; <expression> must evaluate procedure of arity 1
    | (? expression pattern)        ; Apply value to <expression> and match <pattern> on value if result is not #f
                                    ; <expression> must evaluate procedure of arity 1
    | (? pattern)                   ; Match <pattern> on value if value is not #f
    | `quasi-quotation-pattern      ; Quasiquotation pattern matching on lists and vectors
    | _                             ; Wildcard pattern, matches on anything and binds nothing

<quasi-quotation-pattern>
  ::= ,pattern                      ; unquote value and match on <pattern>
    | (quasi-quotation-pattern*)    ; Match when value is list
    | (,@pattern)                   ; unquote splice value and match on <pattern>
    | #(quasi-quotation-pattern*)   ; Match when value is vector

Where expression can be any Chez Scheme expression.

Examples

(import (match))
> (match 5
    ; Match on anything and bind it to x:
    [x (add1 x)])
6
> (match "hello"
    ; Match on string if its length is an even number:
    [x (? (even? (string-length x))) x]
    ; Match on anything:
    [_ 'boo])
'boo
> (match '(1 2 3 4 5 6)
    ; Bind list to ls and match its length with literal 5:
    [(& ls (-> length 5)) ls]
    [_ 'boo])
'boo
> (match '(1 2 3 4 5 6)
    ; Bind list to ls and match if its length is even:
    [(& ls (-> length (? even? _))) (cdr ls)]
    [_ 'boo])
'(2 3 4 5 6)
> (match '(1 2 #(3 4 5) 6 7 8)
    ; Match if third value is vector and its first value equals its length:
    [`(,_ ,_ ,(& (? vector? _) (-> vector-length n) `#(,x 4 5)) ,@ls) (? (= n x)) ls]
    [_ 'boo])
'(6 7 8)

The syntax should be generic enough such that you can implement more specific match syntax for custom data types not natively supported by match:

> (define-record-type my-record (fields x y))
> (match `(1 ,(make-my-record 2 3) 4)
    [`(1 ,(& (? my-record? x) (-> my-record-x 5)) 4) 'nay]
    [`(1 ,(& (? my-record? x) (-> my-record-x 2)) 4) 'yay]
    [_ 'boo])
'yay

More examples can be found in ./match.spec.scm

Notes

I don't know if I'm fighting Chez Scheme but in my mind it would be nice if ./match.scm could only export match but it also needs to export its keywords ?, &, and ->. I managed to embedd sub-macros like match-clause and match-quasiquotation inside match but I can't seem to embedd the keywords. I know it's not a bug in Chez Scheme but it means that if another library use those keywords as macros, there's going to be a conflict which can, as far as I know, only be solved by renaming them.

(import (rename (match) (? new-keyword-name)))
> (match 3 [x (new-keyword-name (odd? x)) 'success])
'success

About

Pattern matching in Chez Scheme

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages