<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array"/>
  <modified type="array">
    <modified>
      <diff>@@ -106,6 +106,4 @@ COMPLETED
 
 * nuke builds for apps with spaces in their names.
 
-* ocaml-like pattern matching, a.k.a. destructuring-bind, though there is still room for improvement here.
-  It would be nice to have something called dcase (destructuring case) that would match the input
-  with the first compatible template, binding variables in it.
\ No newline at end of file
+* ocaml-like pattern matching, a.k.a. destructuring-bind, in destructuring.nu as dbind, dset, and match.</diff>
      <filename>notes/TODO</filename>
    </modified>
    <modified>
      <diff>@@ -41,8 +41,9 @@
 ;; returns a list of bindings like '((a 1) (b 2) (c 3)).
 (function destructure (pat seq)
     (cond
-     ((null? pat)
-      nil)
+     ((and (not pat) seq) 
+      (destruc-throw &quot;Attempt to match empty pattern to non-empty object&quot;))
+     ((not pat) nil)
      ((symbol? pat)
       (let (seq (if (or (pair? seq) (symbol? seq))
                     (then (list 'quote seq))
@@ -52,7 +53,7 @@
       (then (let ((bindings1 (destructure (car pat) (car seq)))
                   (bindings2 (destructure (cdr pat) (cdr seq))))
                 (append bindings1 bindings2))))
-     (else (print &quot;ERROR: pat is not nil, a symbol or a pair: &quot; pat &quot;\n&quot;))))
+     (else (destruc-throw &quot;pattern is not nil, a symbol or a pair: #{pat}&quot;))))
 
 ;; Makes sure that no key is set to two different values.
 ;; For example (check-bindings '((a 1) (a 1) (b 2))) just returns its argument,
@@ -70,9 +71,31 @@
                                    (then 
                                        ;; TODO(issac.trotts@gmail.com): Add a more informative
                                        ;; error message.
-                                       (set exn
-                                            ((NSException alloc) initWithName:&quot;NuDestructuringException&quot;
-                                                                       reason:&quot;Inconsistent bindings&quot;
-                                                                     userInfo:nil))
-                                       (exn raise)))))))
+                                       (destruc-throw &quot;Inconsistent bindings&quot;)))))))
     bindings)
+
+(macro match
+    (set __obj (eval (first margs)))
+    (set __patterns (rest margs))
+    ;; Make __result a list with nils for patterns that don't match, and expressions for ones that do.
+    (set __result
+         (__patterns map:(do (pat-and-body)
+                             (set __pat (first pat-and-body))
+                             (set __body (rest pat-and-body))
+                             (if (eq __pat 'else)
+                                 (then __body)
+                                 (else 
+                                     (try
+                                      (set __bindings (destructure __pat __obj))
+                                      (cons 'let (cons __bindings __body))
+                                      (catch (exception) nil)))))))
+
+    ;; Evaluate and return the first expression that matches.
+    (set __todo (any __result))
+    (eval __todo))
+
+(function destruc-throw (reason)
+    (throw ((NSException alloc) initWithName:&quot;NuDestructuringException&quot;
+                                      reason:reason
+                                    userInfo:nil)))
+</diff>
      <filename>nu/destructuring.nu</filename>
    </modified>
    <modified>
      <diff>@@ -6,7 +6,20 @@
 (load &quot;destructuring&quot;)
 
 (class TestDestructuring is NuTestCase
-     
+
+     ;; match
+     (imethod (id) testMatch is
+         (function people-to-string (people)
+             (match people
+                    (() &quot;no people&quot;)
+                    ((p1) &quot;one person: #{p1}&quot;)
+                    ((p1 p2) &quot;two people: #{p1} and #{p2}&quot;)
+                    (else &quot;too many people: #{(people length)}&quot;)))
+         (assert_equal &quot;no people&quot; (people-to-string '()))
+         (assert_equal &quot;one person: Tim&quot; (people-to-string '(Tim)))
+         (assert_equal &quot;two people: Tim and Matz&quot; (people-to-string '(Tim Matz)))
+         (assert_equal &quot;too many people: 3&quot; (people-to-string '(Tim Guido Matz))))
+
      (imethod (id) testCheckBindings is
          (check-bindings '())  ;; empty set of bindings should not throw
          (check-bindings '((a 1)))</diff>
      <filename>test/test_destructuring.nu</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>e2217384a5cc858d6f42708d8b2d4daeb534124d</id>
    </parent>
  </parents>
  <author>
    <name>Issac Trotts</name>
    <email>issac.trotts@gmail.com</email>
  </author>
  <url>http://github.com/timburks/nu/commit/b499885440d4c77da115eee0f96ecdea1adbf608</url>
  <id>b499885440d4c77da115eee0f96ecdea1adbf608</id>
  <committed-date>2008-07-21T00:07:06-07:00</committed-date>
  <authored-date>2008-07-21T00:06:44-07:00</authored-date>
  <message>Added an OCaml-like match macro.</message>
  <tree>9ca5604a7538553c5f9b009a22340935d2402494</tree>
  <committer>
    <name>Issac Trotts</name>
    <email>issac.trotts@gmail.com</email>
  </committer>
</commit>
