<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0">
<channel>
<title>Clojure Q&amp;A - Recent questions tagged locals clearing</title>
<link>https://ask.clojure.org/index.php/tag/locals%20clearing</link>
<description>Powered by Question2Answer</description>
<item>
<title>Locals clearing + forcing a delay recursively results in NPE</title>
<link>https://ask.clojure.org/index.php/13930/locals-clearing-forcing-a-delay-recursively-results-in-npe</link>
<description>&lt;p&gt;Discovered by Ambrose Bonnaire-Sergeant (@ambrosebs).&lt;/p&gt;
&lt;p&gt;Given this convoluted example:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(let [f +
      p (promise)
      d (delay (f) @@p)]
 (deliver p d)
 @d)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;When executed, it fails with:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;1. Unhandled java.lang.NullPointerException
   Cannot invoke &quot;clojure.lang.IFn.invoke()&quot; because &quot;this.f&quot; is null
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The same error happens with lazy seqs:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(let [f +
      p (promise)
      d (lazy-seq (f) (first @p))]
  (deliver p d)
  (first d))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The reason in both cases is that locals clearing assigns &lt;code&gt;this.f = null;&lt;/code&gt; right after it is first invoked, so when the recursive call reaches &lt;code&gt;(f)&lt;/code&gt; again, the reference is already nil.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(binding [*compiler-options* {:disable-locals-clearing false}]
  (clj-java-decompiler.core/decompile
   (defn repro []
     (let [f +
        p (promise)
        d (delay (f) @@p)]
    (deliver p d)
    @d))))

=&amp;gt;

@Override
public Object invoke() {
    final Object f = this.f;
    this.f = null;
    ((IFn)f).invoke();
    final IFn fn = (IFn)__deref.getRawRoot();
    final IFn fn2 = (IFn)__deref.getRawRoot();
    final Object p = this.p;
    this.p = null;
    final Object invoke = fn2.invoke(p);
    this = null;
    return fn.invoke(invoke);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Is this a bug or undefined behavior?&lt;/p&gt;
</description>
<category>Compiler</category>
<guid isPermaLink="true">https://ask.clojure.org/index.php/13930/locals-clearing-forcing-a-delay-recursively-results-in-npe</guid>
<pubDate>Thu, 30 May 2024 21:11:28 +0000</pubDate>
</item>
<item>
<title>lazy-seq in ClojureScript does not allow for self-referential sequences</title>
<link>https://ask.clojure.org/index.php/11787/lazy-clojurescript-does-allow-self-referential-sequences</link>
<description>&lt;p&gt;For context, started on Slack at &lt;a rel=&quot;nofollow&quot; href=&quot;https://clojurians.slack.com/archives/C03S1L9DN/p1650480331191719&quot;&gt;https://clojurians.slack.com/archives/C03S1L9DN/p1650480331191719&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This code works just fine on CLJ but fails with &lt;code&gt;StackOverflowError&lt;/code&gt; on CLJS:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(def primes (remove
             (fn [x]
               (some #(zero? (mod x %)) primes))
             (iterate inc 2)))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The vital difference between CLJ and CLJS in this case is that in the former, &lt;code&gt;lazy-seq&lt;/code&gt; ends up wrapping its whole body in a function with &lt;code&gt;^:once&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The reasoning why it works that way is because in the code above, the inner &lt;code&gt;primes&lt;/code&gt; is a closed over value, it becomes a local. When the body fn of a &lt;code&gt;lazy-seq&lt;/code&gt; (the one with &lt;code&gt;^:once&lt;/code&gt;) is called the second time, its locals are &lt;code&gt;nil&lt;/code&gt;, so that inner &lt;code&gt;primes&lt;/code&gt; is also &lt;code&gt;nil&lt;/code&gt;. And iteration stops.&lt;br&gt;
In CLJS, there&#039;s no &lt;code&gt;:once&lt;/code&gt; and no locals clearing, so the inner &lt;code&gt;primes&lt;/code&gt; is never &lt;code&gt;nil&lt;/code&gt;, and the execution keeps on going into that &lt;code&gt;fn&lt;/code&gt; without even calling that &lt;code&gt;zero?&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Even if the reasoning doesn&#039;t sound plausible, the hypothesis that it&#039;s indeed &lt;code&gt;:once&lt;/code&gt; that&#039;s to blame for the difference can be easily confirmed by implementing &lt;code&gt;lazy-seq&lt;/code&gt; in CLJ without &lt;code&gt;:once&lt;/code&gt; and noticing that it leads to &lt;code&gt;StackOverflowError&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;It&#039;s unclear to me what to do in this case, but perhaps at least a note on the &lt;a rel=&quot;nofollow&quot; href=&quot;https://clojurescript.org/about/differences&quot;&gt;https://clojurescript.org/about/differences&lt;/a&gt; page should be made about it.&lt;/p&gt;
</description>
<category>ClojureScript</category>
<guid isPermaLink="true">https://ask.clojure.org/index.php/11787/lazy-clojurescript-does-allow-self-referential-sequences</guid>
<pubDate>Wed, 20 Apr 2022 21:02:56 +0000</pubDate>
</item>
</channel>
</rss>