diff options
author | Rich Hickey <richhickey@gmail.com> | 2007-09-25 02:52:20 +0000 |
---|---|---|
committer | Rich Hickey <richhickey@gmail.com> | 2007-09-25 02:52:20 +0000 |
commit | 176a660fb3d4a6136dc342b082288e4f29048dfc (patch) | |
tree | 956652738cecfecd83f43d5a0b9a8ef8a213820d | |
parent | 0b4986c73ce6b158cf21ea48c8aedf774a3d0b7f (diff) |
map, filter, reduce
-rw-r--r-- | clojure.markdown | 35 | ||||
-rw-r--r-- | src/boot.clj | 35 | ||||
-rw-r--r-- | src/jvm/clojure/lang/Compiler.java | 8 | ||||
-rw-r--r-- | src/jvm/clojure/lang/RT.java | 10 |
4 files changed, 78 insertions, 10 deletions
diff --git a/clojure.markdown b/clojure.markdown index ad4ee565..7dc9c489 100644 --- a/clojure.markdown +++ b/clojure.markdown @@ -51,7 +51,7 @@ Clojure is [hosted on SourceForge][sf]. Feedback and discussion should occur on the [Clojure Google Group][cgg]. -Clojure is delivered in a zip file containing a single .jar, `clojure.jar`. It requires the [ASM 3.0 bytecode library][asm], and the current alpha distribution does not bundle it. `asm, asm-analysis, asm-commons and asm-util` jars are currently required. [Java][jdk] 1.5 or greater is required. +Clojure is delivered in a zip file containing a single .jar, `clojure.jar`. It requires the [ASM 3.0 bytecode library][asm], and the current alpha distribution includes it. [Java][jdk] 1.5 or greater is required. [asm]: http://asm.objectweb.org/ @@ -60,13 +60,13 @@ Clojure is delivered in a zip file containing a single .jar, `clojure.jar`. It r [cgg]: http://groups.google.com/group/clojure <h2 id="quickstart">Quick Start</h2> -Put the Clojure and ASM jars on the classpath and launch `java clojure.lang.Compiler`. This will bring up a simple read-eval-print loop (REPL). Much of Clojure is defined in Clojure itself, so the first thing you need to do is load the `boot.clj` file included in the distribution: +Put the Clojure jar on the classpath and launch `java clojure.lang.Compiler /your/path/to/src/boot.clj`. This will bring up a simple read-eval-print loop (REPL). Much of Clojure is defined in Clojure itself (in `boot.clj`), so the first thing you need to do is load the `boot.clj` file included in the `src` directory of distribution, either on the command line as above or as follows: <pre><code> -(load-file "/your/path/to/boot.clj") +(load-file "/your/path/to/src/boot.clj") </code></pre> -In the alpha, this will spew a bunch of bytecode as it compiles the file. This is to help me (and you) diagnose any code generation problems. After boot.clj is loaded you will have the language as described herein fully available. +After boot.clj is loaded you will have the language as described herein fully available. Try: @@ -184,7 +184,7 @@ The behavior of the reader is driven by a combination of built-in constructs and (def x 5) (def lst '(a b c)) - (fred x ~x lst ~@lst 7 8 :nine) + `(fred x ~x lst ~@lst 7 8 :nine) > (user/fred user/x 5 user/lst a b c 7 8 :nine) @@ -391,6 +391,31 @@ Note - *you cannot assign to function params or local bindings. Only Java fields These are synchronization primitives that should be avoided in user code. Use the `locking` macro. <h2 id="macros">Macros</h2> +Clojure has a programmatic macro system which allows the compiler to be extended by user code. Macros can be used to define syntactic constructs which would require primitives or built-in support in other languages. Many core constructs of Clojure are not, in fact, primitives, but are normal macros. First we'll cover some of the included macros and then look at the facilities for creating your own. + +--- +### (*and* exprs*) +Evaluates exprs one at a time, from left to right. If a form returns `nil`, `and` returns `nil` and doesn't evaluate any of the other expressions, otherwise it returns the value of the last expr. `(and)` returns `t`. + +--- +### (*or* exprs*) +Evaluates exprs one at a time, from left to right. If a form returns a non-nil value, `or` returns that value and doesn't evaluate any of the other expressions, otherwise it returns `nil`. `(or)` returns `nil`. + +--- +### (*cond* test-expr-pairs*) +test-expr-pair => test expr + +`cond` takes a set of test/expr pairs. It evaluates each test one at a time. If a test returns non-nil, `cond` evaluates and returns the value of the corresponding expr and doesn't evaluate any of the other tests or exprs. `(cond)` returns `nil`. `cond ` is a succinct and readable alternative to nested `if`s. + +--- +### (*defn* name [params* ] exprs*) +### (*defn* name ([params* ] exprs*)+) +Same as `(def name (fn [params* ] exprs*))` or `(def name (fn ([params* ] exprs*)+))` + +--- +### (*defmacro* name [params* ] exprs*) +### (*defmacro* name ([params* ] exprs*)+) +Like defn, but the resulting function name is declared as a macro and will be used as a macro by the compiler when it is called. <h2 id="datastructures">Data Structures</h2> diff --git a/src/boot.clj b/src/boot.clj index feb835f2..3726a5bb 100644 --- a/src/boot.clj +++ b/src/boot.clj @@ -318,3 +318,38 @@ `(. clojure.lang.LockingTransaction (runInTransaction (fn [] ~@body)))) +; sequence fns +(defn every [pred coll] + (if (seq coll) + (and (pred (first coll)) + (recur pred (rest coll))) + t)) + +(defn map + ([f coll] + (if (seq coll) + (lazy-cons (f (first coll)) (map f (rest coll))) + nil)) + ([f coll & colls] + (if (and (seq coll) (every seq colls)) + (lazy-cons (apply f (first coll) (map first colls)) + (apply map f (rest coll) (map rest colls))) + nil))) + +(defn filter [f coll] + (if (seq coll) + (let [v (f (first coll))] + (if v + (lazy-cons (first coll) (filter f (rest coll))) + (recur f (rest coll)))) + nil)) + +(defn reduce + ([f coll] + (if (seq coll) + (thisfn f (rest coll) (first coll)) + (f))) + ([f coll val] + (if (seq coll) + (recur f (rest coll) (f val (first coll))) + val)))
\ No newline at end of file diff --git a/src/jvm/clojure/lang/Compiler.java b/src/jvm/clojure/lang/Compiler.java index 877c20a1..b0c9c8d0 100644 --- a/src/jvm/clojure/lang/Compiler.java +++ b/src/jvm/clojure/lang/Compiler.java @@ -2667,6 +2667,7 @@ public static void main(String[] args){ //repl LineNumberingPushbackReader rdr = new LineNumberingPushbackReader(new InputStreamReader(System.in)); OutputStreamWriter w = new OutputStreamWriter(System.out); + Object EOF = new Object(); try { @@ -2676,6 +2677,7 @@ public static void main(String[] args){ RT.CURRENT_NS, RT.CURRENT_NS.get(), SOURCE, "REPL" )); + w.write("Clojure\n"); for(; ;) { @@ -2693,7 +2695,7 @@ public static void main(String[] args){ w.write('\n'); //w.flush(); } - catch(Exception e) + catch(Throwable e) { e.printStackTrace(); } @@ -2703,6 +2705,10 @@ public static void main(String[] args){ } } } + catch(Exception e) + { + e.printStackTrace(); + } finally { Var.popThreadBindings(); diff --git a/src/jvm/clojure/lang/RT.java b/src/jvm/clojure/lang/RT.java index 765e704e..844e911d 100644 --- a/src/jvm/clojure/lang/RT.java +++ b/src/jvm/clojure/lang/RT.java @@ -235,9 +235,10 @@ static public ISeq cons(Object x, ISeq y){ } static public Object first(Object x){ - if(x == null) + ISeq seq = seq(x); + if(seq == null) return null; - return seq(x).first(); + return seq.first(); } static public Object second(Object x){ @@ -253,9 +254,10 @@ static public Object fourth(Object x){ } static public ISeq rest(Object x){ - if(x == null) + ISeq seq = seq(x); + if(seq == null) return null; - return seq(x).rest(); + return seq.rest(); } static public ISeq rrest(Object x){ |