GitXplorerGitXplorer
p

patterns

public
1 stars
1 forks
0 issues

Commits

List of commits on branch master.
Unverified
816279cea8d5e3179d631e139b9c8757565fb4a9

prepare for v1, bump

ppolux committed 11 years ago
Unverified
45126fb77e983a64d1da6abff7cd080337fdefb0

add constraints for deps

ppolux committed 11 years ago
Unverified
2564f49bff58fb46f0bb80d15e5f61fe83379085

sync readme with example

ppolux committed 11 years ago
Unverified
43581ec28d7394af3af1fd053d437bd0d9b9dcf4

make pubspec pub ready

ppolux committed 11 years ago
Unverified
685ccb357ce31654a134d77db94e3e379b2b0cf7

fix code block in readme

ppolux committed 11 years ago
Unverified
89dc55f3b8804f3b8eecac2047de8cad09ba299d

rename lib

ppolux committed 11 years ago

README

The README file for this repository.

Pattern Matching Combinators for Dart

A small set of combinators for defining extractors (à la Wadler/Scala/F#), patterns and rules. The only doc so far is that quick demo, but it demoes all the features of the library.

import 'package:patterns/patterns.dart';
import 'package:persistent/persistent.dart';

// We define linked lists.

class LList {}
class Nil implements LList {
  toString() => "Nil()";
}
class Cons implements LList {
  final x;
  final LList xs;
  Cons(this.x, this.xs);
  toString() => "Cons($x, $xs)";
}

// This is boilerplate code that can be automatically derived from the
// definition of Nil and Cons. Note that patterns are typed:
// cons(eq(1), eq(2)) is ill-typed according to Dart's type system. You can
// also define more exotic patterns, like a pattern that matches any even number
// for instance.

OPattern<LList> nil() =>
    constructor([],
        (s) => (s is Nil) ? new Option.some([]) : new Option.none());
OPattern<LList> cons(OPattern p1, OPattern<LList> p2) =>
    constructor([p1, p2],
        (s) => (s is Cons) ? new Option.some([s.x, s.xs]) : new Option.none());

main() {
  final list = new Cons(1, new Cons(2, new Cons(3, new Nil())));

  // The right-hand side of the first rule that matches (in this case the
  // last one) is executed. "pvar" denote pattern variables.

  match(list).against(
      nil()                              >> (_) { throw "should not happen"; }
    | cons(v('x'), nil())                >> (_) { throw "should not happen"; }
    | cons(v('x'), cons(eq(1), v('xs'))) >> (_) { throw "should not happen"; }
    | cons(v('x'), cons(eq(2), v('xs'))) >> (e) { print("match: ${e['x']} ${e['xs']}"); }
  ); // prints "match: 1 Cons(3, Nil())"

  // Match returns a value: the value returned by the executed right-hand side.

  final tailOfTail = match(list).against(
      cons(v('_'), cons(v('_'), v('xs'))) >> (e) { return e['xs']; }  // _ is a wildcard
  );
  print(tailOfTail); // prints "Cons(3, Nil())"

  // Non-linear patterns are supported.

  final nonLinear = cons(v('x'), cons(v('x'), nil()));

  match(new Cons(1, new Cons(2, new Nil()))).against(
      nonLinear >> (_) { print("bad"); }
    | v('_')    >> (_) { print("good"); }
  );
  match(new Cons(1, new Cons(1, new Nil()))).against(
      nonLinear >> (_) { print("good"); }
  );

  // If no branch matches, a MatchFailure is raised.

  try {
    match(list).against(
        nil() >> (_) {  throw "should not happen"; }
    );
  } on MatchFailure catch (_) {
    print("failed as intended");
  }

  // Subpatterns can be aliased with %

  match(list).against(
      cons(v('_'), v('xs') % cons(v('_'), v('x'))) >> (e) { print("${e['xs']} ${e['x']}"); }
  ); // prints "Cons(2, Cons(3, Nil())) Cons(3, Nil())"

  // Guards allow to put extra conditions on patterns.

  match(list).against(
      cons(v('x'), v('_')) & guard((e) => e['x'] > 1) >> (_) { throw "impossible"; }
                           & otherwise                >> (e) { print("x = ${e['x']}"); }
    | nil()                                           >> (_) { throw "impossible"; }
  ); // prints "x = 1"

  // The obligatory map function.

  LList map(Function f, LList xs) =>
      match(xs).against(
          nil()                 >> (_) { return new Nil(); }
        | cons(v('y'), v('ys')) >> (e) { return new Cons(f(e['y']), map(f, e['ys'])); }
      );
  print(map((n) => n + 1, list));
}

Try it!

git clone https://github.com/polux/patterns
cd patterns
pub install
dart example/example.dart