<!-- 
RSS generated by JIRA (4.4#649-r158309) at Mon May 20 02:25:12 CDT 2013

It is possible to restrict the fields that are returned in this document by specifying the 'field' parameter in your request.
For example, to request only the issue key and summary add field=key&field=summary to the URL of your request.
For example:
http://dev.clojure.org/jira/si/jira.issueviews:issue-xml/CLJ-415/CLJ-415.xml?field=key&field=summary
-->
<rss version="0.92" >
<channel>
    <title>Clojure JIRA</title>
    <link>http://dev.clojure.org/jira</link>
    <description>This file is an XML representation of an issue</description>
    <language>en-us</language>    <build-info>
        <version>4.4</version>
        <build-number>649</build-number>
        <build-date>25-07-2011</build-date>
    </build-info>

<item>
            <title>[CLJ-415] smarter assert (prints locals)</title>
                <link>http://dev.clojure.org/jira/browse/CLJ-415</link>
                <project id="10010" key="CLJ">Clojure</project>
                        <description>&lt;p&gt;Here is an implementation you can paste into a repl. Feedback wanted:&lt;/p&gt;

&lt;div class=&quot;code panel&quot; style=&quot;border-width: 1px;&quot;&gt;&lt;div class=&quot;codeContent panelContent&quot;&gt;
&lt;pre class=&quot;code-java&quot;&gt;(defn ^{:&lt;span class=&quot;code-keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;code-keyword&quot;&gt;true&lt;/span&gt;} local-bindings
  &lt;span class=&quot;code-quote&quot;&gt;&quot;Produces a map of the names of local bindings to their values.&quot;&lt;/span&gt;
  [env]
  (let [symbols (map key env)]
    (zipmap (map (fn [sym] `(quote ~sym)) symbols) symbols)))

(defmacro &lt;span class=&quot;code-keyword&quot;&gt;assert&lt;/span&gt;
  &quot;Evaluates expr and &lt;span class=&quot;code-keyword&quot;&gt;throws&lt;/span&gt; an exception &lt;span class=&quot;code-keyword&quot;&gt;if&lt;/span&gt; it does not evaluate to
 logical &lt;span class=&quot;code-keyword&quot;&gt;true&lt;/span&gt;.&quot;
  {:added &lt;span class=&quot;code-quote&quot;&gt;&quot;1.0&quot;&lt;/span&gt;}
  [x]
  (when *&lt;span class=&quot;code-keyword&quot;&gt;assert&lt;/span&gt;*
    (let [bindings (local-bindings &amp;amp;env)]
      `(when-not ~x
         (let [sep# (&lt;span class=&quot;code-object&quot;&gt;System&lt;/span&gt;/getProperty &lt;span class=&quot;code-quote&quot;&gt;&quot;line.separator&quot;&lt;/span&gt;)]
           (&lt;span class=&quot;code-keyword&quot;&gt;throw&lt;/span&gt; (AssertionError. (apply str &lt;span class=&quot;code-quote&quot;&gt;&quot;Assert failed: &quot;&lt;/span&gt; (pr-str &apos;~x) sep#
                                          (map (fn [[k# v#]] (str &lt;span class=&quot;code-quote&quot;&gt;&quot;\t&quot;&lt;/span&gt; k# &lt;span class=&quot;code-quote&quot;&gt;&quot; : &quot;&lt;/span&gt; v# sep#)) ~bindings)))))))))&lt;/pre&gt;
&lt;/div&gt;&lt;/div&gt;</description>
                <environment></environment>
            <key id="13812">CLJ-415</key>
            <summary>smarter assert (prints locals)</summary>
                <type id="4" iconUrl="http://dev.clojure.org/jira/images/icons/improvement.gif">Enhancement</type>
                                <priority id="3" iconUrl="http://dev.clojure.org/jira/images/icons/priority_major.gif">Major</priority>
                    <status id="1" iconUrl="http://dev.clojure.org/jira/images/icons/status_open.gif">Open</status>
                    <resolution id="-1">Unresolved</resolution>
                                <assignee username="-1">Unassigned</assignee>
                                <reporter username="importer">Assembla Importer</reporter>
                        <labels>
                    </labels>
                <created>Thu, 29 Jul 2010 17:45:00 -0500</created>
                <updated>Sun, 18 Nov 2012 01:06:07 -0600</updated>
                                                    <fixVersion>Approved Backlog</fixVersion>
                                        <due></due>
                    <votes>2</votes>
                        <watches>3</watches>
                        <comments>
                    <comment id="24161" author="importer" created="Tue, 24 Aug 2010 17:41:00 -0500"  >&lt;p&gt;Converted from &lt;a href=&quot;http://www.assembla.com/spaces/clojure/tickets/415&quot;&gt;http://www.assembla.com/spaces/clojure/tickets/415&lt;/a&gt;&lt;/p&gt;</comment>
                    <comment id="24162" author="importer" created="Tue, 24 Aug 2010 17:41:00 -0500"  >&lt;p&gt;alexdmiller said: A simple example I tried for illustration:&lt;/p&gt;

&lt;div class=&quot;code panel&quot; style=&quot;border-width: 1px;&quot;&gt;&lt;div class=&quot;codeContent panelContent&quot;&gt;
&lt;pre class=&quot;code-java&quot;&gt;user=&amp;gt; (let [a 1 b 2] (&lt;span class=&quot;code-keyword&quot;&gt;assert&lt;/span&gt; (= a b)))
#&amp;lt;CompilerException java.lang.AssertionError: Assert failed: (= a b)
 a : 1
 b : 2&lt;/pre&gt;
&lt;/div&gt;&lt;/div&gt;</comment>
                    <comment id="24163" author="importer" created="Tue, 24 Aug 2010 17:41:00 -0500"  >&lt;p&gt;fogus said: Of course it&apos;s weird if you do something like:&lt;/p&gt;
&lt;div class=&quot;code panel&quot; style=&quot;border-width: 1px;&quot;&gt;&lt;div class=&quot;codeContent panelContent&quot;&gt;
&lt;pre class=&quot;code-java&quot;&gt;(let [x 1 y 2 z 3 a 1 b 2 c 3] (&lt;span class=&quot;code-keyword&quot;&gt;assert&lt;/span&gt; (= x y)))
java.lang.AssertionError: Assert failed: (= x y)
 x : 1
 y : 2
 z : 3
 a : 1
 b : 2
 c : 3
 (NO_SOURCE_FILE:0)
&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;

So maybe it could be slightly changed to:
&amp;lt;pre&amp;gt;&amp;lt;code&amp;gt;(defmacro &lt;span class=&quot;code-keyword&quot;&gt;assert&lt;/span&gt;
  &lt;span class=&quot;code-quote&quot;&gt;&quot;Evaluates expr and &lt;span class=&quot;code-keyword&quot;&gt;throws&lt;/span&gt; an exception &lt;span class=&quot;code-keyword&quot;&gt;if&lt;/span&gt; it does not evaluate to logical &lt;span class=&quot;code-keyword&quot;&gt;true&lt;/span&gt;.&quot;&lt;/span&gt;
  {:added &lt;span class=&quot;code-quote&quot;&gt;&quot;1.0&quot;&lt;/span&gt;}
  [x]
  (when *&lt;span class=&quot;code-keyword&quot;&gt;assert&lt;/span&gt;*
    (let [bindings (local-bindings &amp;amp;env)]
      `(when-not ~x
         (let [sep#  (&lt;span class=&quot;code-object&quot;&gt;System&lt;/span&gt;/getProperty &lt;span class=&quot;code-quote&quot;&gt;&quot;line.separator&quot;&lt;/span&gt;)
               form# &apos;~x]
           (&lt;span class=&quot;code-keyword&quot;&gt;throw&lt;/span&gt; (AssertionError. (apply str &lt;span class=&quot;code-quote&quot;&gt;&quot;Assert failed: &quot;&lt;/span&gt; (pr-str form#) sep#
                                          (map (fn [[k# v#]] 
                                                 (when (some #{k#} form#) 
                                                   (str &lt;span class=&quot;code-quote&quot;&gt;&quot;\t&quot;&lt;/span&gt; k# &lt;span class=&quot;code-quote&quot;&gt;&quot; : &quot;&lt;/span&gt; v# sep#))) 
                                               ~bindings)))))))))
&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;

So that. now it&apos;s just:
&amp;lt;pre&amp;gt;&amp;lt;code&amp;gt;(let [x 1 y 2 z 3 a 1 b 2 c 3] (&lt;span class=&quot;code-keyword&quot;&gt;assert&lt;/span&gt; (= x y)))
java.lang.AssertionError: Assert failed: (= x y)
 x : 1
 y : 2
 (NO_SOURCE_FILE:0)&lt;/pre&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;:f&lt;/p&gt;</comment>
                    <comment id="24164" author="importer" created="Tue, 24 Aug 2010 17:41:00 -0500"  >&lt;p&gt;fogus said: Hmmm, but that fails entirely for: (let &lt;span class=&quot;error&quot;&gt;&amp;#91;x 1 y 2 z 3 a 1 b 2 c 3&amp;#93;&lt;/span&gt; (assert (= &lt;span class=&quot;error&quot;&gt;&amp;#91;x y&amp;#93;&lt;/span&gt; &lt;span class=&quot;error&quot;&gt;&amp;#91;a c&amp;#93;&lt;/span&gt;))).  So maybe it&apos;s better just to print all of the locals unless you really want to get complicated.&lt;br/&gt;
:f&lt;/p&gt;</comment>
                    <comment id="24165" author="importer" created="Tue, 24 Aug 2010 17:41:00 -0500"  >&lt;p&gt;jawolfe said: See also some comments in:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://groups.google.com/group/clojure-dev/browse_frm/thread/68d49cd7eb4a4899/9afc6be4d3f8ae27?lnk=gst&amp;amp;q=assert#9afc6be4d3f8ae27&quot;&gt;http://groups.google.com/group/clojure-dev/browse_frm/thread/68d49cd7eb4a4899/9afc6be4d3f8ae27?lnk=gst&amp;amp;q=assert#9afc6be4d3f8ae27&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Plus one more suggestion to add to the mix:  in addition to / instead of printing the locals, how about saving them somewhere.  For example, the var &lt;b&gt;assert-bindings&lt;/b&gt; could be bound to the map of locals.  This way you don&apos;t run afoul of infinite/very large sequences, and allow the user to do more detailed interrogation of the bad values (especially useful when some of the locals print opaquely).&lt;/p&gt;</comment>
                    <comment id="24166" author="importer" created="Tue, 24 Aug 2010 17:41:00 -0500"  >&lt;p&gt;stuart.sierra said: Another approach, which I wil willingly donate:&lt;br/&gt;
&lt;a href=&quot;http://github.com/stuartsierra/lazytest/blob/master/src/main/clojure/lazytest/expect.clj&quot;&gt;http://github.com/stuartsierra/lazytest/blob/master/src/main/clojure/lazytest/expect.clj&lt;/a&gt;&lt;/p&gt;</comment>
                    <comment id="26034" author="jweiss" created="Wed, 15 Dec 2010 13:33:52 -0600"  >&lt;p&gt;There&apos;s one more tweak to fogus&apos;s last comment, which I&apos;m actually using.  You need to flatten the quoted form before you can use &apos;some&apos; to check whether the local was used in the form:&lt;/p&gt;

&lt;div class=&quot;code panel&quot; style=&quot;border-width: 1px;&quot;&gt;&lt;div class=&quot;codeContent panelContent&quot;&gt;
&lt;pre class=&quot;code-java&quot;&gt;(defmacro &lt;span class=&quot;code-keyword&quot;&gt;assert&lt;/span&gt;
  &lt;span class=&quot;code-quote&quot;&gt;&quot;Evaluates expr and &lt;span class=&quot;code-keyword&quot;&gt;throws&lt;/span&gt; an exception &lt;span class=&quot;code-keyword&quot;&gt;if&lt;/span&gt; it does not evaluate to logical &lt;span class=&quot;code-keyword&quot;&gt;true&lt;/span&gt;.&quot;&lt;/span&gt;
  {:added &lt;span class=&quot;code-quote&quot;&gt;&quot;1.0&quot;&lt;/span&gt;}
  [x]
  (when *&lt;span class=&quot;code-keyword&quot;&gt;assert&lt;/span&gt;*
    (let [bindings (local-bindings &amp;amp;env)]
      `(when-not ~x
         (let [sep#  (&lt;span class=&quot;code-object&quot;&gt;System&lt;/span&gt;/getProperty &lt;span class=&quot;code-quote&quot;&gt;&quot;line.separator&quot;&lt;/span&gt;)
               form# &apos;~x]
           (&lt;span class=&quot;code-keyword&quot;&gt;throw&lt;/span&gt; (AssertionError. (apply str &lt;span class=&quot;code-quote&quot;&gt;&quot;Assert failed: &quot;&lt;/span&gt; (pr-str form#) sep#
                                          (map (fn [[k# v#]] 
                                                 (when (some #{k#} (flatten form#)) 
                                                   (str &lt;span class=&quot;code-quote&quot;&gt;&quot;\t&quot;&lt;/span&gt; k# &lt;span class=&quot;code-quote&quot;&gt;&quot; : &quot;&lt;/span&gt; v# sep#))) 
                                               ~bindings)))))))))&lt;/pre&gt;
&lt;/div&gt;&lt;/div&gt;</comment>
                    <comment id="26087" author="stu" created="Tue, 4 Jan 2011 20:31:17 -0600"  >&lt;p&gt;I am holding off on this until we have more solidity around &lt;a href=&quot;http://dev.clojure.org/display/design/Error+Handling&quot;&gt;http://dev.clojure.org/display/design/Error+Handling&lt;/a&gt;. (Considering, for instance, having &lt;b&gt;all&lt;/b&gt; exceptions thrown from Clojure provide access to locals.)&lt;/p&gt;

&lt;p&gt;When my pipe dream fades I will come back and screen this before the next release.&lt;/p&gt;</comment>
                    <comment id="26194" author="stu" created="Fri, 28 Jan 2011 13:14:13 -0600"  >&lt;p&gt;Why try to guess what someone wants to do with the locals (or any other context, for that matter) when you can specify a callback (see below). This would have been useful last week when I had an assertion that failed only on the CI box, where no debugger is available.&lt;/p&gt;

&lt;p&gt;Rich, at the risk of beating a dead horse, I still think this is a good idea. Debuggers are not always available, and this is an example of where a Lisp is intrinsically capable of providing better information than can be had in other environments. If you want a patch for the code below please mark waiting on me, otherwise please decline this ticket so I stop looking at it. &lt;img class=&quot;emoticon&quot; src=&quot;http://dev.clojure.org/jira/images/icons/emoticons/smile.gif&quot; height=&quot;20&quot; width=&quot;20&quot; align=&quot;absmiddle&quot; alt=&quot;&quot; border=&quot;0&quot;/&gt;&lt;/p&gt;

&lt;div class=&quot;code panel&quot; style=&quot;border-width: 1px;&quot;&gt;&lt;div class=&quot;codeContent panelContent&quot;&gt;
&lt;pre class=&quot;code-java&quot;&gt;(def ^:dynamic *&lt;span class=&quot;code-keyword&quot;&gt;assert&lt;/span&gt;-handler* nil)

(defn ^{:&lt;span class=&quot;code-keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;code-keyword&quot;&gt;true&lt;/span&gt;} local-bindings
  &lt;span class=&quot;code-quote&quot;&gt;&quot;Produces a map of the names of local bindings to their values.&quot;&lt;/span&gt;
  [env]
  (let [symbols (map key env)]
    (zipmap (map (fn [sym] `(quote ~sym)) symbols) symbols)))

(defmacro &lt;span class=&quot;code-keyword&quot;&gt;assert&lt;/span&gt;
  [x]
  (when *&lt;span class=&quot;code-keyword&quot;&gt;assert&lt;/span&gt;*
    (let [bindings (local-bindings &amp;amp;env)]
      `(when-not ~x
         (let [sep#  (&lt;span class=&quot;code-object&quot;&gt;System&lt;/span&gt;/getProperty &lt;span class=&quot;code-quote&quot;&gt;&quot;line.separator&quot;&lt;/span&gt;)
               form# &apos;~x]
           (&lt;span class=&quot;code-keyword&quot;&gt;if&lt;/span&gt; *&lt;span class=&quot;code-keyword&quot;&gt;assert&lt;/span&gt;-handler*
             (*&lt;span class=&quot;code-keyword&quot;&gt;assert&lt;/span&gt;-handler* form# ~bindings)
             (&lt;span class=&quot;code-keyword&quot;&gt;throw&lt;/span&gt; (AssertionError. (apply str &lt;span class=&quot;code-quote&quot;&gt;&quot;Assert failed: &quot;&lt;/span&gt; (pr-str form#) sep#
                                            (map (fn [[k# v#]] 
                                                   (when (some #{k#} (flatten form#)) 
                                                     (str &lt;span class=&quot;code-quote&quot;&gt;&quot;\t&quot;&lt;/span&gt; k# &lt;span class=&quot;code-quote&quot;&gt;&quot; : &quot;&lt;/span&gt; v# sep#))) 
                                                 ~bindings))))))))))&lt;/pre&gt;
&lt;/div&gt;&lt;/div&gt;</comment>
                    <comment id="26461" author="jweiss" created="Fri, 27 May 2011 08:16:40 -0500"  >&lt;p&gt;A slight improvement I made in my own version of this code:  flatten does not affect set literals.  So if you do (assert (some #{x} &lt;span class=&quot;error&quot;&gt;&amp;#91;a b c d&amp;#93;&lt;/span&gt;))  the value of x will not be printed.  Here&apos;s a modified flatten that does the job:&lt;/p&gt;

&lt;div class=&quot;code panel&quot; style=&quot;border-width: 1px;&quot;&gt;&lt;div class=&quot;codeContent panelContent&quot;&gt;
&lt;pre class=&quot;code-none&quot;&gt;(defn symbols [sexp]
  &quot;Returns just the symbols from the expression, including those
   inside literals (sets, maps, lists, vectors).&quot;
  (distinct (filter symbol? (tree-seq coll? seq sexp))))&lt;/pre&gt;
&lt;/div&gt;&lt;/div&gt;</comment>
                    <comment id="29961" author="jafingerhut" created="Sun, 18 Nov 2012 01:06:07 -0600"  >&lt;p&gt;Attaching git format patch clj-415-assert-prints-locals-v1.txt of Stuart Halloway&apos;s version of this idea.  I&apos;m not advocating it over the other variations, just getting a file attached to the JIRA ticket.&lt;/p&gt;</comment>
                </comments>
                    <attachments>
                    <attachment id="11684" name="clj-415-assert-prints-locals-v1.txt" size="1581" author="jafingerhut" created="Sun, 18 Nov 2012 01:06:07 -0600" />
                </attachments>
            <subtasks>
        </subtasks>
                <customfields>
                                <customfield id="customfield_10002" key="com.atlassian.jira.plugin.system.customfieldtypes:select">
                <customfieldname>Approval</customfieldname>
                <customfieldvalues>
                        <customfieldvalue key="10006">Incomplete</customfieldvalue>

                </customfieldvalues>
            </customfield>
                                                                                    <customfield id="customfield_10010" key="com.pyxis.greenhopper.jira:gh-global-rank">
                <customfieldname>Global Rank</customfieldname>
                <customfieldvalues>
                    
                </customfieldvalues>
            </customfield>
                                                                                                        <customfield id="customfield_10003" key="com.atlassian.jira.plugin.system.customfieldtypes:userpicker">
                <customfieldname>Waiting On</customfieldname>
                <customfieldvalues>
                    <customfieldvalue>richhickey</customfieldvalue>
                </customfieldvalues>
            </customfield>
                            </customfields>
    </item>
</channel>
</rss>