diff options
author | Rich Hickey <richhickey@gmail.com> | 2007-10-27 12:07:21 +0000 |
---|---|---|
committer | Rich Hickey <richhickey@gmail.com> | 2007-10-27 12:07:21 +0000 |
commit | 7b1999c497f9e39c01a2b9f5d628f22df701c0e3 (patch) | |
tree | f3a7b08546b0911f0631c20cf3fcb8e5ec01be3d /src | |
parent | a90826fc6f3cba8f4541a2a4e02739de6e7954a1 (diff) |
rename new-proxy to implement, rename .-> to doto, rename dolist to doseq, added into, memfn, fnseq. Made FnSeq not use Delay
Diffstat (limited to 'src')
-rw-r--r-- | src/boot.clj | 46 | ||||
-rw-r--r-- | src/jvm/clojure/lang/Compiler.java | 2 | ||||
-rw-r--r-- | src/jvm/clojure/lang/FnSeq.java | 41 |
3 files changed, 60 insertions, 29 deletions
diff --git a/src/boot.clj b/src/boot.clj index 04031be6..587d7098 100644 --- a/src/boot.clj +++ b/src/boot.clj @@ -108,8 +108,12 @@ (defmacro delay [& body] (list 'new 'clojure.lang.Delay (list* 'fn [] body))) +(defn fnseq [x restfn] + (new clojure.lang.FnSeq x restfn)) + (defmacro lazy-cons [x & body] - (list 'new 'clojure.lang.FnSeq x (list* 'delay body))) + (list 'fnseq x (list* 'fn [] body))) + (defn concat ([] nil) @@ -493,7 +497,7 @@ (defn defimports [& imports-maps] (def *imports* (apply merge imports-maps))) -(defmacro dolist [item list & body] +(defmacro doseq [item list & body] `(loop [list# (seq ~list)] (when list# (let [~item (first list#)] @@ -511,21 +515,21 @@ (let [#^clojure.lang.Var imps *ns-imports* pkg (ffirst import-lists) classes (rfirst import-lists)] - (dolist c classes + (doseq c classes (. imps (bindRoot (assoc (. imps (get)) c (strcat pkg "." c)))))) (apply thisfn (rest import-lists)))) (defn unimport [& names] (let [#^clojure.lang.Var imps *ns-imports*] - (dolist name names + (doseq name names (. imps (bindRoot (dissoc (. imps (get)) name)))))) (defn refer [& refer-lists] - (dolist rlist refer-lists + (doseq rlist refer-lists (let [#^clojure.lang.Var refers *ns-refers* ns (first rlist) names (rest rlist)] - (dolist name names + (doseq name names (when (. clojure.lang.Var (find (sym (str *current-namespace*) (str name)))) (throw (new Exception (strcat "Name conflict: " name " already exists in this namespace")))) (let [varsym (sym (str ns) (str name)) @@ -540,7 +544,7 @@ (defn unrefer [& names] (let [#^clojure.lang.Var refers *ns-refers*] - (dolist name names + (doseq name names (. refers (bindRoot (dissoc (. refers (get)) name)))))) (defn unintern [varsym] @@ -549,6 +553,12 @@ (defn into-array [aseq] (. clojure.lang.RT (seqToTypedArray (seq aseq)))) +(defn into [to from] + (let [ret to items (seq from)] + (if items + (recur (conj ret (first items)) (rest items)) + ret))) + (defn array [& items] (into-array items)) @@ -558,7 +568,7 @@ (into-array classes) (new clojure.lang.ProxyHandler method-map)))) -(defmacro new-proxy [classes & fs] +(defmacro implement [classes & fs] `(make-proxy ~(apply vector (map (appl list 'class) classes)) ~(loop [fmap {} fs fs] @@ -594,16 +604,21 @@ ([stream eof-error? eof-value recursive?] (. clojure.lang.LispReader (read stream eof-error? eof-value recursive?)))) -(defmacro .-> [x & members] +(defmacro doto [x & members] (let [gx (gensym)] `(let [~gx ~x] (do ~@(map (fn [m] (list '. gx m)) members))))) + +(defmacro memfn [name & args] + `(fn [target# ~@args] + (. target# (~name ~@args)))) + (defmacro time [expr] `(let [start# (. System (nanoTime)) ret# ~expr] - (prn (strcat "Elapsed time: " (/ (- (. System (nanoTime)) start#) 1000000.0)" msecs")) + (prn (strcat "Elapsed time: " (/ (- (. System (nanoTime)) start#) 1000000.0) " msecs")) ret#)) (def *exports* @@ -615,7 +630,7 @@ nil? not first rest second ffirst frest rfirst rrest eql? str strcat gensym cond - apply list* delay lazy-cons concat + apply list* delay lazy-cons fnseq concat and or + * / - == < <= > >= inc dec pos? neg? zero? complement constantly identity seq count @@ -630,12 +645,13 @@ map mapcat filter take take-while drop drop-while zipmap cycle split-at split-with repeat replicate iterate range - dolist dotimes + doseq dotimes into eval import unimport refer unrefer in-namespace unintern into-array array - make-proxy new-proxy - prn print newline *out* *current-namespace* .-> - read *in* + make-proxy implement + prn print newline *out* *current-namespace* + doto memfn + read *in* time )) diff --git a/src/jvm/clojure/lang/Compiler.java b/src/jvm/clojure/lang/Compiler.java index 13a7fcf3..fa3a0e52 100644 --- a/src/jvm/clojure/lang/Compiler.java +++ b/src/jvm/clojure/lang/Compiler.java @@ -825,7 +825,7 @@ static class StaticMethodExpr extends MethodExpr{ List methods = Reflector.getMethods(Class.forName(className), args.count(), methodName, true); if(methods.isEmpty()) - throw new IllegalArgumentException("No matching method found"); + throw new IllegalArgumentException("No matching method: " + methodName); method = (java.lang.reflect.Method) ((methods.size() == 1) ? methods.get(0) : null); } diff --git a/src/jvm/clojure/lang/FnSeq.java b/src/jvm/clojure/lang/FnSeq.java index 48211217..99f8429e 100644 --- a/src/jvm/clojure/lang/FnSeq.java +++ b/src/jvm/clojure/lang/FnSeq.java @@ -13,17 +13,20 @@ package clojure.lang; public class FnSeq extends ASeq{
final Object _first;
-final Delay _rest;
+IFn _restFn;
+volatile ISeq _rest;
-public FnSeq(Object first, Delay rest){
+public FnSeq(Object first, IFn restFn){
this._first = first;
- this._rest = rest;
+ this._restFn = restFn;
+ this._rest = this;
}
-public FnSeq(IPersistentMap meta, Object first, Delay rest){
+public FnSeq(IPersistentMap meta, Object first, IFn restFn, ISeq rest){
super(meta);
this._first = first;
this._rest = rest;
+ this._restFn = restFn;
}
public Object first(){
@@ -31,17 +34,29 @@ public Object first(){ }
public ISeq rest(){
- try
- {
- return (ISeq) _rest.invoke();
- }
- catch(Exception e)
- {
- throw new Error(e.toString());
- }
+ if(_restFn != null)
+ synchronized(this)
+ {
+ if(_restFn != null)
+ {
+ try
+ {
+ _rest = (ISeq) _restFn.invoke();
+ }
+ catch(Exception ex)
+ {
+ throw new Error(ex);
+ }
+ _restFn = null;
+ }
+ }
+ return _rest;
}
public FnSeq withMeta(IPersistentMap meta){
- return new FnSeq(meta, _first, _rest);
+ if(meta == meta())
+ return this;
+ return new FnSeq(meta, _first, _restFn, _rest);
}
+
}
|