Mercurial > lasercutter
view src/clojure/contrib/fcase.clj @ 10:ef7dbbd6452c
added clojure source goodness
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Sat, 21 Aug 2010 06:25:44 -0400 |
parents | |
children |
line wrap: on
line source
1 ;;; fcase.clj -- simple variants of "case" for Clojure3 ;; by Stuart Sierra, http://stuartsierra.com/4 ;; April 7, 20086 ;; Copyright (c) Stuart Sierra, 2008. All rights reserved. The use7 ;; and distribution terms for this software are covered by the Eclipse8 ;; Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)9 ;; which can be found in the file epl-v10.html at the root of this10 ;; distribution. By using this software in any fashion, you are11 ;; agreeing to be bound by the terms of this license. You must not12 ;; remove this notice, or any other, from this software.15 ;; This file defines a generic "case" macro called "fcase" which takes16 ;; the equality-testing function as an argument. It also defines a17 ;; traditional "case" macro that tests using "=" and variants that18 ;; test for regular expressions and class membership.21 ;; Note (December 23, 2008): This library has been supplanted by the22 ;; inclusion of "condp" in clojure.core as of Clojure SVN rev. 1180.25 (ns26 ^{:author "Stuart Sierra",27 :doc "This file defines a generic \"case\" macro called \"fcase\" which takes28 the equality-testing function as an argument. It also defines a29 traditional \"case\" macro that tests using \"=\" and variants that30 test for regular expressions and class membership.33 Note (December 23, 2008): This library has been supplanted by the34 inclusion of \"condp\" in clojure.core as of Clojure SVN rev. 1180."}36 clojure.contrib.fcase37 (:refer-clojure :exclude (case)))40 (defmacro fcase41 "Generic switch/case macro. 'fcase' is short for 'function case'.43 The 'compare-fn' is a fn of two arguments.45 The 'test-expr-clauses' are value-expression pairs without46 surrounding parentheses, like in Clojure's 'cond'.48 The 'case-value' is evaluated once and cached. Then, 'compare-fn'49 is called once for each clause, with the clause's test value as its50 first argument and 'case-value' as its second argument. If51 'compare-fn' returns logical true, the clause's expression is52 evaluated and returned. If 'compare-fn' returns false/nil, we go to53 the next test value.55 If 'test-expr-clauses' contains an odd number of items, the last56 item is the default expression evaluated if no case-value matches.57 If there is no default expression and no case-value matches, fcase58 returns nil.60 See specific forms of this macro in 'case' and 're-case'.62 The test expressions in 'fcase' are always evaluated linearly, in63 order. For a large number of case expressions it may be more64 efficient to use a hash lookup."65 [compare-fn case-value &66 test-expr-clauses]67 (let [test-val-sym (gensym "test_val")68 test-fn-sym (gensym "test_fn")69 cond-loop (fn this [clauses]70 (cond71 (>= (count clauses) 2)72 (list 'if (list test-fn-sym (first clauses) test-val-sym)73 (second clauses)74 (this (rest (rest clauses))))75 (= (count clauses) 1) (first clauses)))]76 (list 'let [test-val-sym case-value, test-fn-sym compare-fn]77 (cond-loop test-expr-clauses))))79 (defmacro case80 "Like cond, but test-value is compared against the value of each81 test expression with =. If they are equal, executes the \"body\"82 expression. Optional last expression is executed if none of the83 test expressions match."84 [test-value & clauses]85 `(fcase = ~test-value ~@clauses))87 (defmacro re-case88 "Like case, but the test expressions are regular expressions, tested89 with re-find."90 [test-value & clauses]91 `(fcase re-find ~test-value ~@clauses))93 (defmacro instance-case94 "Like case, but the test expressions are Java class names, tested with95 'instance?'."96 [test-value & clauses]97 `(fcase instance? ~test-value ~@clauses))99 (defn in-case-test [test-seq case-value]100 (some (fn [item] (= item case-value))101 test-seq))103 (defmacro in-case104 "Like case, but test expressions are sequences. The test expression105 is true if any item in the sequence is equal (tested with '=') to106 the test value."107 [test-value & clauses]108 `(fcase in-case-test ~test-value ~@clauses))