<!-- 
RSS generated by JIRA (4.4#649-r158309) at Tue Jun 18 23:28:42 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-906/CLJ-906.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-906] defrecord with protocol implementation fails when field and method names collide</title>
                <link>http://dev.clojure.org/jira/browse/CLJ-906</link>
                <project id="10010" key="CLJ">Clojure</project>
                        <description>&lt;p&gt;The following produces a NullPointerException:&lt;/p&gt;

&lt;p&gt;(defprotocol Foo (act &lt;span class=&quot;error&quot;&gt;&amp;#91;this&amp;#93;&lt;/span&gt;))&lt;br/&gt;
(defrecord Fred []&lt;br/&gt;
  Foo&lt;br/&gt;
  (act &lt;span class=&quot;error&quot;&gt;&amp;#91;this&amp;#93;&lt;/span&gt; (println &quot;done.&quot;)))&lt;br/&gt;
(defrecord Bar &lt;span class=&quot;error&quot;&gt;&amp;#91;act&amp;#93;&lt;/span&gt; ;; &amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;======= Field name is the same as method name.&lt;br/&gt;
  Foo&lt;br/&gt;
  (act &lt;span class=&quot;error&quot;&gt;&amp;#91;this&amp;#93;&lt;/span&gt; (act (Fred.)))) ;; &amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;====== Behaves as (nil (Fred.))&lt;br/&gt;
(act (Bar. nil))&lt;/p&gt;

&lt;p&gt;Produces:&lt;br/&gt;
Exception in thread &quot;main&quot; java.lang.NullPointerException&lt;br/&gt;
 at protocol.Bar.act(protocol.clj:8)&lt;br/&gt;
 at protocol$eval66.invoke(protocol.clj:9)&lt;br/&gt;
 at clojure.lang.Compiler.eval(Compiler.java:6465)&lt;br/&gt;
 at clojure.lang.Compiler.load(Compiler.java:6902)&lt;br/&gt;
 at clojure.lang.Compiler.loadFile(Compiler.java:6863)&lt;br/&gt;
 at clojure.main$load_script.invoke(main.clj:282)&lt;br/&gt;
 at clojure.main$script_opt.invoke(main.clj:342)&lt;br/&gt;
 at clojure.main$main.doInvoke(main.clj:426)&lt;br/&gt;
 at clojure.lang.RestFn.invoke(RestFn.java:408)&lt;br/&gt;
 at clojure.lang.Var.invoke(Var.java:401)&lt;br/&gt;
 at clojure.lang.AFn.applyToHelper(AFn.java:161)&lt;br/&gt;
 at clojure.lang.Var.applyTo(Var.java:518)&lt;br/&gt;
 at clojure.main.main(main.java:37)&lt;/p&gt;

&lt;p&gt;&amp;#8211;&lt;/p&gt;

&lt;p&gt;The following works as expected:&lt;/p&gt;

&lt;p&gt;(defprotocol Foo (act &lt;span class=&quot;error&quot;&gt;&amp;#91;this&amp;#93;&lt;/span&gt;))&lt;br/&gt;
(defrecord Fred []&lt;br/&gt;
  Foo&lt;br/&gt;
  (act &lt;span class=&quot;error&quot;&gt;&amp;#91;this&amp;#93;&lt;/span&gt; (println &quot;done.&quot;)))&lt;br/&gt;
(defrecord Bar &lt;span class=&quot;error&quot;&gt;&amp;#91;x&amp;#93;&lt;/span&gt; ; &amp;lt;&amp;lt;== Field name is the DIFFERENT than method name&lt;br/&gt;
  Foo&lt;br/&gt;
  (act &lt;span class=&quot;error&quot;&gt;&amp;#91;this&amp;#93;&lt;/span&gt; (act (Fred.))))&lt;br/&gt;
(act (Bar. &lt;span class=&quot;error&quot;&gt;&amp;#91;1 2 3&amp;#93;&lt;/span&gt;))&lt;/p&gt;

&lt;p&gt;Produces:&lt;br/&gt;
&quot;done.&quot;&lt;/p&gt;

&lt;p&gt;&amp;#8211;&lt;/p&gt;

&lt;p&gt;The following also works:&lt;/p&gt;

&lt;p&gt;(defprotocol Foo (act &lt;span class=&quot;error&quot;&gt;&amp;#91;this&amp;#93;&lt;/span&gt;))&lt;br/&gt;
(defrecord Fred [])&lt;br/&gt;
(defrecord Bar &lt;span class=&quot;error&quot;&gt;&amp;#91;act&amp;#93;&lt;/span&gt;) ; &amp;lt;&amp;lt;== Field name is the same as method name&lt;br/&gt;
(extend-protocol Foo&lt;br/&gt;
  Fred&lt;br/&gt;
  (act &lt;span class=&quot;error&quot;&gt;&amp;#91;this&amp;#93;&lt;/span&gt; (println &quot;done.&quot;))&lt;br/&gt;
  Bar&lt;br/&gt;
  (act &lt;span class=&quot;error&quot;&gt;&amp;#91;this&amp;#93;&lt;/span&gt; (act (Fred.))))&lt;br/&gt;
(act (Bar. &lt;span class=&quot;error&quot;&gt;&amp;#91;1 2 3&amp;#93;&lt;/span&gt;))&lt;/p&gt;</description>
                <environment></environment>
            <key id="15093">CLJ-906</key>
            <summary>defrecord with protocol implementation fails when field and method names collide</summary>
                <type id="1" iconUrl="http://dev.clojure.org/jira/images/icons/bug.gif">Defect</type>
                                <priority id="3" iconUrl="http://dev.clojure.org/jira/images/icons/priority_major.gif">Major</priority>
                    <status id="6" iconUrl="http://dev.clojure.org/jira/images/icons/status_closed.gif">Closed</status>
                    <resolution id="2">Declined</resolution>
                                <assignee username="-1">Unassigned</assignee>
                                <reporter username="bstiles">Brian Stiles</reporter>
                        <labels>
                    </labels>
                <created>Sun, 1 Jan 2012 19:30:39 -0600</created>
                <updated>Fri, 1 Mar 2013 12:46:58 -0600</updated>
                    <resolved>Tue, 27 Nov 2012 14:07:33 -0600</resolved>
                            <version>Release 1.2</version>
                <version>Release 1.3</version>
                                                        <due></due>
                    <votes>0</votes>
                        <watches>2</watches>
                        <comments>
                    <comment id="30061" author="halgari" created="Tue, 27 Nov 2012 14:03:58 -0600"  >&lt;p&gt;The thing to remember here is that protocol functions are not (only) methods on a class, they are functions global to the namespace. So notice the subtle difference here:&lt;/p&gt;

&lt;p&gt;user=&amp;gt; (defprotocol Foo (act &lt;span class=&quot;error&quot;&gt;&amp;#91;this&amp;#93;&lt;/span&gt;))&lt;br/&gt;
Foo&lt;br/&gt;
user=&amp;gt; (defrecord Fred &lt;span class=&quot;error&quot;&gt;&amp;#91;act&amp;#93;&lt;/span&gt; Foo (act &lt;span class=&quot;error&quot;&gt;&amp;#91;this&amp;#93;&lt;/span&gt; (act this)))&lt;br/&gt;
user.Fred&lt;br/&gt;
user=&amp;gt; (Fred. 42)&lt;br/&gt;
#user.Fred{:act 42}&lt;br/&gt;
user=&amp;gt; (act (Fred. 42))&lt;br/&gt;
ClassCastException java.lang.Long cannot be cast to clojure.lang.IFn  user.Fred (NO_SOURCE_FILE:1)&lt;/p&gt;

&lt;p&gt;user=&amp;gt; (defrecord Fred &lt;span class=&quot;error&quot;&gt;&amp;#91;act&amp;#93;&lt;/span&gt; Foo (act &lt;span class=&quot;error&quot;&gt;&amp;#91;this&amp;#93;&lt;/span&gt; (user/act this)))&lt;br/&gt;
user.Fred&lt;br/&gt;
user=&amp;gt; (act (Fred. 42))&lt;br/&gt;
StackOverflowError   user.Fred (NO_SOURCE_FILE:1)&lt;/p&gt;

&lt;p&gt;So, it you want to access the data, you can use &quot;act&quot; directly, if you want to recursively call act (the protocol function), you can use recur, or the fully qualified name. Also, since these are records we&apos;re talking about, the following also works:&lt;/p&gt;

&lt;p&gt;user=&amp;gt; (defrecord Fred &lt;span class=&quot;error&quot;&gt;&amp;#91;act&amp;#93;&lt;/span&gt; Foo (act &lt;span class=&quot;error&quot;&gt;&amp;#91;this&amp;#93;&lt;/span&gt; (:act this)))&lt;br/&gt;
user.Fred&lt;br/&gt;
user=&amp;gt; (act (Fred. 42))&lt;br/&gt;
42&lt;/p&gt;</comment>
                    <comment id="30062" author="halgari" created="Tue, 27 Nov 2012 14:07:33 -0600"  >&lt;p&gt;Declined since this is not really a bug. There is a work-around and no obvious solution to the more general problem of defrecord name collisions. If this still bugs you, please feel free to bring it up on clojure-dev, and we&apos;ll open a new ticket once a discussion has been had. &lt;/p&gt;</comment>
                </comments>
                    <attachments>
                </attachments>
            <subtasks>
        </subtasks>
                <customfields>
                                <customfield id="customfield_10002" key="com.atlassian.jira.plugin.system.customfieldtypes:select">
                <customfieldname>Approval</customfieldname>
                <customfieldvalues>
                        <customfieldvalue key="10008">Not Approved</customfieldvalue>

                </customfieldvalues>
            </customfield>
                                                                                    <customfield id="customfield_10010" key="com.pyxis.greenhopper.jira:gh-global-rank">
                <customfieldname>Global Rank</customfieldname>
                <customfieldvalues>
                    
                </customfieldvalues>
            </customfield>
                                                                                                            </customfields>
    </item>
</channel>
</rss>