Mercurial > lasercutter
comparison 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 |
comparison
equal
deleted
inserted
replaced
9:35cf337adfcf | 10:ef7dbbd6452c |
---|---|
1 ;;; fcase.clj -- simple variants of "case" for Clojure | |
2 | |
3 ;; by Stuart Sierra, http://stuartsierra.com/ | |
4 ;; April 7, 2008 | |
5 | |
6 ;; Copyright (c) Stuart Sierra, 2008. All rights reserved. The use | |
7 ;; and distribution terms for this software are covered by the Eclipse | |
8 ;; 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 this | |
10 ;; distribution. By using this software in any fashion, you are | |
11 ;; agreeing to be bound by the terms of this license. You must not | |
12 ;; remove this notice, or any other, from this software. | |
13 | |
14 | |
15 ;; This file defines a generic "case" macro called "fcase" which takes | |
16 ;; the equality-testing function as an argument. It also defines a | |
17 ;; traditional "case" macro that tests using "=" and variants that | |
18 ;; test for regular expressions and class membership. | |
19 | |
20 | |
21 ;; Note (December 23, 2008): This library has been supplanted by the | |
22 ;; inclusion of "condp" in clojure.core as of Clojure SVN rev. 1180. | |
23 | |
24 | |
25 (ns | |
26 ^{:author "Stuart Sierra", | |
27 :doc "This file defines a generic \"case\" macro called \"fcase\" which takes | |
28 the equality-testing function as an argument. It also defines a | |
29 traditional \"case\" macro that tests using \"=\" and variants that | |
30 test for regular expressions and class membership. | |
31 | |
32 | |
33 Note (December 23, 2008): This library has been supplanted by the | |
34 inclusion of \"condp\" in clojure.core as of Clojure SVN rev. 1180."} | |
35 | |
36 clojure.contrib.fcase | |
37 (:refer-clojure :exclude (case))) | |
38 | |
39 | |
40 (defmacro fcase | |
41 "Generic switch/case macro. 'fcase' is short for 'function case'. | |
42 | |
43 The 'compare-fn' is a fn of two arguments. | |
44 | |
45 The 'test-expr-clauses' are value-expression pairs without | |
46 surrounding parentheses, like in Clojure's 'cond'. | |
47 | |
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 its | |
50 first argument and 'case-value' as its second argument. If | |
51 'compare-fn' returns logical true, the clause's expression is | |
52 evaluated and returned. If 'compare-fn' returns false/nil, we go to | |
53 the next test value. | |
54 | |
55 If 'test-expr-clauses' contains an odd number of items, the last | |
56 item is the default expression evaluated if no case-value matches. | |
57 If there is no default expression and no case-value matches, fcase | |
58 returns nil. | |
59 | |
60 See specific forms of this macro in 'case' and 're-case'. | |
61 | |
62 The test expressions in 'fcase' are always evaluated linearly, in | |
63 order. For a large number of case expressions it may be more | |
64 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 (cond | |
71 (>= (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)))) | |
78 | |
79 (defmacro case | |
80 "Like cond, but test-value is compared against the value of each | |
81 test expression with =. If they are equal, executes the \"body\" | |
82 expression. Optional last expression is executed if none of the | |
83 test expressions match." | |
84 [test-value & clauses] | |
85 `(fcase = ~test-value ~@clauses)) | |
86 | |
87 (defmacro re-case | |
88 "Like case, but the test expressions are regular expressions, tested | |
89 with re-find." | |
90 [test-value & clauses] | |
91 `(fcase re-find ~test-value ~@clauses)) | |
92 | |
93 (defmacro instance-case | |
94 "Like case, but the test expressions are Java class names, tested with | |
95 'instance?'." | |
96 [test-value & clauses] | |
97 `(fcase instance? ~test-value ~@clauses)) | |
98 | |
99 (defn in-case-test [test-seq case-value] | |
100 (some (fn [item] (= item case-value)) | |
101 test-seq)) | |
102 | |
103 (defmacro in-case | |
104 "Like case, but test expressions are sequences. The test expression | |
105 is true if any item in the sequence is equal (tested with '=') to | |
106 the test value." | |
107 [test-value & clauses] | |
108 `(fcase in-case-test ~test-value ~@clauses)) |