In the lazy branch, empty sequences don't always evaluate as
false in a boolean context.  Tracking down places you've
made this assumption can be hard.  Attached is a patch that
helps by providing a flag, assert-if-lazy-seq.

When this flag is on, 'if' is replaced with a new (slower)
version that throws an exception if you're using a lazy-seq
as the test expression.  This is almost always an error in
the lazy branch, and usually just requires wrapping the
lazy-seq in a call to 'seq', as has been discussed
elsewhere.

To turn on the flag you need to rebuild clojure with an
extra option, like this:

ant -Dclojure.assert-if-lazy-seq=please

Any non-empty string will do for the value.

You will need to set the value at runtime as well.  There
may be a way to avoid this, but I haven't thought of how.
So for now you'll want at the top of your code:

(reset! *assert-if-lazy-seq* true)

Now anytime you try to use nil punning, you should get an
exception.

user=> (when (filter neg? [1 2]) :all-pos)
java.lang.Exception: LazySeq used in 'if' (NO_SOURCE_FILE:0)

user=> (not (concat))
java.lang.Exception: LazySeq used in 'if' (NO_SOURCE_FILE:0)

--Chouser

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To post to this group, send email to clojure@googlegroups.com
To unsubscribe from this group, send email to 
clojure+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~----------~----~----~----~------~----~------~--~---

commit b0cec18fb925510502352d8fdcc0a4b93b28bd72
Author: Chouser <chou...@n01se.net>
Date:   Fri Feb 13 13:02:30 2009 -0500

    Add assert-if-lazy-seq

diff --git a/branches/lazy/build.xml b/branches/lazy/build.xml
index 04583ba..bc5fcc7 100644
--- a/branches/lazy/build.xml
+++ b/branches/lazy/build.xml
@@ -11,6 +11,7 @@
   <property name="build" location="classes"/>
   <property name="clojure_jar" location="clojure.jar"/>
   <property name="slim_jar" location="clojure-slim.jar"/>
+  <property name="clojure.assert-if-lazy-seq" value=""/>
 
   <target name="init" depends="clean">
     <tstamp/>
@@ -28,6 +29,7 @@
     <java classname="clojure.lang.Compile"
           classpath="${build}:${cljsrc}">
       <sysproperty key="clojure.compile.path" value="${build}"/>
+      <sysproperty key="clojure.assert-if-lazy-seq" value="${clojure.assert-if-lazy-seq}"/>
       <arg value="clojure.core"/>
       <arg value="clojure.main"/>
       <arg value="clojure.set"/>
diff --git a/branches/lazy/src/clj/clojure/core.clj b/branches/lazy/src/clj/clojure/core.clj
index eb31005..8f2ec15 100644
--- a/branches/lazy/src/clj/clojure/core.clj
+++ b/branches/lazy/src/clj/clojure/core.clj
@@ -36,6 +36,10 @@
  fn (fn* fn [& decl] (cons 'fn* decl)))
 
 (def
+ #^{:macro true}
+ if (fn* if [& decl] (cons 'if* decl)))
+
+(def
  #^{:arglists '([coll])
     :doc "Returns the first item in the collection. Calls seq on its
     argument. If coll is nil, returns nil."}
@@ -291,6 +295,19 @@
 
 (. (var defmacro) (setMacro))
 
+(def *assert-if-lazy-seq*
+  (let [x (System/getProperty "clojure.assert-if-lazy-seq")]
+    (new clojure.lang.Atom (if x (if (.isEmpty x) false true)))))
+
+(defmacro if [tst & etc]
+  (if* (.get *assert-if-lazy-seq*)
+    (let [tstsym 'no-gensym-for-me]
+      (list 'let [tstsym tst]
+	(list 'if* (list 'instance? clojure.lang.LazySeq tstsym)
+           (list 'throw (list 'new Exception "LazySeq used in 'if'"))
+	   (cons 'if* (cons tstsym etc)))))
+    (cons 'if* (cons tst etc))))
+
 (defmacro when
   "Evaluates test. If logical true, evaluates body in an implicit do."
   [test & body]
@@ -1642,7 +1659,7 @@
   ([coll]
    (sort compare coll))
   ([#^java.util.Comparator comp coll]
-   (when (and coll (not (zero? (count coll))))
+   (when (seq coll)
      (let [a (to-array coll)]
        (. java.util.Arrays (sort a comp))
        (seq a)))))
diff --git a/branches/lazy/src/clj/clojure/core_proxy.clj b/branches/lazy/src/clj/clojure/core_proxy.clj
index 8517e23..edbc78f 100644
--- a/branches/lazy/src/clj/clojure/core_proxy.clj
+++ b/branches/lazy/src/clj/clojure/core_proxy.clj
@@ -155,7 +155,7 @@
                              meths (concat 
                                     (seq (. c (getDeclaredMethods)))
                                     (seq (. c (getMethods))))]
-                        (if meths 
+                        (if (seq meths)
                           (let [#^java.lang.reflect.Method meth (first meths)
                                 mods (. meth (getModifiers))
                                 mk (method-sig meth)]
diff --git a/branches/lazy/src/jvm/clojure/lang/Compiler.java b/branches/lazy/src/jvm/clojure/lang/Compiler.java
index 664045f..b29876f 100644
--- a/branches/lazy/src/jvm/clojure/lang/Compiler.java
+++ b/branches/lazy/src/jvm/clojure/lang/Compiler.java
@@ -40,7 +40,7 @@ public class Compiler implements Opcodes{
 static final Symbol DEF = Symbol.create("def");
 static final Symbol LOOP = Symbol.create("loop*");
 static final Symbol RECUR = Symbol.create("recur");
-static final Symbol IF = Symbol.create("if");
+static final Symbol IF = Symbol.create("if*");
 static final Symbol LET = Symbol.create("let*");
 static final Symbol DO = Symbol.create("do");
 static final Symbol FN = Symbol.create("fn*");

Reply via email to