CL Extensions: CONTROL FLOW
 

Control Flow

In order to make the use of the UNIFICATION library easier, a few utility macros are provided. The macros MATCH, MATCHING, and MATCH-CASE can be used to unify two (or more) objects and then to build a lexical environment where the variables present in the to objects (or templates) are bound to the values resulting from the application of UNIFY.

  • MATCH is a "single shot" macro. It does one unification and executes forms in an appropriate lexical environment.
  • MATCH-CASE is equivalent to CASE. It tries to match a single object (or template) against a set of clauses. The forms associated to the first clause for which there is a successful unification, are then executed within an appropriate lexical environment.
  • MATCHING is equivalent to COND. Each clause contains a head consisting of two objects to be unified. The first clause whose head unifies sucessfully has its associated forms executed within an appropriate lexical environment.

There are also the macro MATCHF and MATCHF-CASE, which do not evaluate the pattern; they can be used to produce more streamlined code.

Examples

These macros allow the construction of interesting pattern matching like code.

  (defun factorial (x)
    (match-case (x)
      (0 1)
      (#T(number ?n) (* ?n (factorial (1- ?n))))
      (otherwise (error "Incorrect match for ~S." x))))
  

Or consider the more interesting piece of code from a not-so hypothetical Red-Black tree implementation (cfr. [O98].) The function BALANCE is the key part of the rebalancing act played by Red-Black trees.

  (defstruct (tree-node (:conc-name tn-)
                        (:constructor mk-tn (color left elem right)))
     color
     left
     elem
     right)

  (defun balance (&rest balancing-arguments)
    (match-case (balancing-arguments)
      ((:black #T(tree-node tn-color :red
                            tn-left #T(tree-node tn-color :red
                                                 tn-left ?a
                                                 tn-elem ?x
                                                 tn-right ?b)
                            tn-elem ?y
                            tn-right ?c)
               ?z
               ?d)
        (mk-tn :red (mk-tn :black ?a ?x ?b) ?y (mk-tn :black ?c ?z ?d)))
      ((:black #T(tree-node tn-color :red
                            tn-left ?a
                            tn-elem ?x
                            tn-right #T(tree-node tn-color :red
                                                  tn-left ?b
                                                  tn-elem ?y
                                                  tn-right ?c))
               ?z
               ?d)
        (mk-tn :red (mk-tn :black ?a ?x ?b) ?y (mk-tn :black ?c ?z ?d)))
      ((:black ?a
               ?x
               #T(tree-node tn-color :red
                            tn-left #T(tree-node tn-color :red
                                                 tn-left ?b
                                                 tn-elem ?y
                                                 tn-right ?c)
                            tn-elem ?z
                            tn-right ?d))
        (mk-tn :red (mk-tn :black ?a ?x ?b) ?y (mk-tn :black ?c ?z ?d)))
      ((:black ?a
               ?x
               #T(tree-node tn-color :red
                            tn-left ?b
                            tn-elem ?y
                            tn-left #T(tree-node tn-color :red
                                                 tn-left ?c
                                                 tn-elem ?z
                                                 tn-right ?d)))
        (mk-tn :red (mk-tn :black ?a ?x ?b) ?y (mk-tn :black ?c ?z ?d)))
      ((?color ?left ?elem ?right)
        (mk-tn ?color ?left ?elem ?right))))
  

This version of BALANCE is more verbose than the one given in [O98], but it preserves the general elegance of the ML implementation.

Control Flow Dictionary

Notes

Other Forms

It would be obvious to add the macros EMATCH-CASE and CMATCH-CASE, for symmetry with ECASE and CCASE. Also, MATCHING could be renamed to MATCH-COND.

Current Implementation Details

The current implementations of MATCHING and MATCH-CASE do not handle user supplied environments yet.

References

[O98] C. Okasaki, Purely Functional Data Structures, Cambridge University Press, 1998.