summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRich Hickey <richhickey@gmail.com>2007-09-25 02:52:20 +0000
committerRich Hickey <richhickey@gmail.com>2007-09-25 02:52:20 +0000
commit176a660fb3d4a6136dc342b082288e4f29048dfc (patch)
tree956652738cecfecd83f43d5a0b9a8ef8a213820d
parent0b4986c73ce6b158cf21ea48c8aedf774a3d0b7f (diff)
map, filter, reduce
-rw-r--r--clojure.markdown35
-rw-r--r--src/boot.clj35
-rw-r--r--src/jvm/clojure/lang/Compiler.java8
-rw-r--r--src/jvm/clojure/lang/RT.java10
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){