aboutsummaryrefslogtreecommitdiff
path: root/modules/fcase
diff options
context:
space:
mode:
Diffstat (limited to 'modules/fcase')
-rw-r--r--modules/fcase/pom.xml16
-rw-r--r--modules/fcase/src/main/clojure/clojure/contrib/fcase.clj108
2 files changed, 124 insertions, 0 deletions
diff --git a/modules/fcase/pom.xml b/modules/fcase/pom.xml
new file mode 100644
index 00000000..1fb6f9a8
--- /dev/null
+++ b/modules/fcase/pom.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http//www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
+ http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.clojure.contrib</groupId>
+ <artifactId>parent</artifactId>
+ <version>1.3.0-SNAPSHOT</version>
+ <relativePath>../parent</relativePath>
+ </parent>
+ <artifactId>fcase</artifactId>
+ <dependencies>
+ </dependencies>
+</project> \ No newline at end of file
diff --git a/modules/fcase/src/main/clojure/clojure/contrib/fcase.clj b/modules/fcase/src/main/clojure/clojure/contrib/fcase.clj
new file mode 100644
index 00000000..4d0fc184
--- /dev/null
+++ b/modules/fcase/src/main/clojure/clojure/contrib/fcase.clj
@@ -0,0 +1,108 @@
+;;; fcase.clj -- simple variants of "case" for Clojure
+
+;; by Stuart Sierra, http://stuartsierra.com/
+;; April 7, 2008
+
+;; Copyright (c) Stuart Sierra, 2008. All rights reserved. The use
+;; and distribution terms for this software are covered by the Eclipse
+;; Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
+;; which can be found in the file epl-v10.html at the root of this
+;; distribution. By using this software in any fashion, you are
+;; agreeing to be bound by the terms of this license. You must not
+;; remove this notice, or any other, from this software.
+
+
+;; This file defines a generic "case" macro called "fcase" which takes
+;; the equality-testing function as an argument. It also defines a
+;; traditional "case" macro that tests using "=" and variants that
+;; test for regular expressions and class membership.
+
+
+;; Note (December 23, 2008): This library has been supplanted by the
+;; inclusion of "condp" in clojure.core as of Clojure SVN rev. 1180.
+
+
+(ns
+ ^{:author "Stuart Sierra",
+ :doc "This file defines a generic \"case\" macro called \"fcase\" which takes
+the equality-testing function as an argument. It also defines a
+traditional \"case\" macro that tests using \"=\" and variants that
+test for regular expressions and class membership.
+
+
+Note (December 23, 2008): This library has been supplanted by the
+inclusion of \"condp\" in clojure.core as of Clojure SVN rev. 1180."}
+
+ clojure.contrib.fcase
+ (:refer-clojure :exclude (case)))
+
+
+(defmacro fcase
+ "Generic switch/case macro. 'fcase' is short for 'function case'.
+
+ The 'compare-fn' is a fn of two arguments.
+
+ The 'test-expr-clauses' are value-expression pairs without
+ surrounding parentheses, like in Clojure's 'cond'.
+
+ The 'case-value' is evaluated once and cached. Then, 'compare-fn'
+ is called once for each clause, with the clause's test value as its
+ first argument and 'case-value' as its second argument. If
+ 'compare-fn' returns logical true, the clause's expression is
+ evaluated and returned. If 'compare-fn' returns false/nil, we go to
+ the next test value.
+
+ If 'test-expr-clauses' contains an odd number of items, the last
+ item is the default expression evaluated if no case-value matches.
+ If there is no default expression and no case-value matches, fcase
+ returns nil.
+
+ See specific forms of this macro in 'case' and 're-case'.
+
+ The test expressions in 'fcase' are always evaluated linearly, in
+ order. For a large number of case expressions it may be more
+ efficient to use a hash lookup."
+ [compare-fn case-value &
+ test-expr-clauses]
+ (let [test-val-sym (gensym "test_val")
+ test-fn-sym (gensym "test_fn")
+ cond-loop (fn this [clauses]
+ (cond
+ (>= (count clauses) 2)
+ (list 'if (list test-fn-sym (first clauses) test-val-sym)
+ (second clauses)
+ (this (rest (rest clauses))))
+ (= (count clauses) 1) (first clauses)))]
+ (list 'let [test-val-sym case-value, test-fn-sym compare-fn]
+ (cond-loop test-expr-clauses))))
+
+(defmacro case
+ "Like cond, but test-value is compared against the value of each
+ test expression with =. If they are equal, executes the \"body\"
+ expression. Optional last expression is executed if none of the
+ test expressions match."
+ [test-value & clauses]
+ `(fcase = ~test-value ~@clauses))
+
+(defmacro re-case
+ "Like case, but the test expressions are regular expressions, tested
+ with re-find."
+ [test-value & clauses]
+ `(fcase re-find ~test-value ~@clauses))
+
+(defmacro instance-case
+ "Like case, but the test expressions are Java class names, tested with
+ 'instance?'."
+ [test-value & clauses]
+ `(fcase instance? ~test-value ~@clauses))
+
+(defn in-case-test [test-seq case-value]
+ (some (fn [item] (= item case-value))
+ test-seq))
+
+(defmacro in-case
+ "Like case, but test expressions are sequences. The test expression
+ is true if any item in the sequence is equal (tested with '=') to
+ the test value."
+ [test-value & clauses]
+ `(fcase in-case-test ~test-value ~@clauses))