<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0">
<channel>
<title>Clojure Q&amp;A - Recent questions</title>
<link>https://ask.clojure.org/index.php/questions</link>
<description></description>
<item>
<title>tools.reader project file version is outdated</title>
<link>https://ask.clojure.org/index.php/15209/tools-reader-project-file-version-is-outdated</link>
<description>&lt;p&gt;Hello! I noticed version currently defined in the tools.reader &lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/clojure/tools.reader/blob/master/project.clj#L1&quot;&gt;project.clj file&lt;/a&gt; is out of date with respect to the &lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/clojure/tools.reader/releases/tag/v1.6.0&quot;&gt;latest git tag&lt;/a&gt;. Would it be possible to keep those in sync? This situation is making packaging the library for Debian a bit more complicated than it needs to be. Thanks!&lt;/p&gt;
</description>
<category>tools.reader</category>
<guid isPermaLink="true">https://ask.clojure.org/index.php/15209/tools-reader-project-file-version-is-outdated</guid>
<pubDate>Tue, 04 Aug 2026 02:36:36 +0000</pubDate>
</item>
<item>
<title>tools.build copy task does not respect non-replaced-exts</title>
<link>https://ask.clojure.org/index.php/15208/tools-build-copy-task-does-not-respect-non-replaced-exts</link>
<description>&lt;p&gt;It is not possible to tell &lt;code&gt;tools.build&lt;/code&gt; to copy files without substitution for a custom set of file extensions because the &lt;code&gt;copy&lt;/code&gt; function does not actually use its parameter (&lt;code&gt;non-replaced-exts&lt;/code&gt;) - it always uses &lt;code&gt;default-non-replaced-exts&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(defn copy
  [{:keys [target-dir src-dirs include replace ignores non-replaced-exts]
    :or {include &quot;**&quot;, ignores default-ignores, non-replaced-exts default-non-replaced-exts}
    :as _params}]
  (let [to-path (.toPath (file/ensure-dir (api/resolve-path target-dir)))
        ignore-regexes (map re-pattern ignores)
        non-replaced (map #(str &quot;.&quot; %) default-non-replaced-exts)]
  ...)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The binding &lt;code&gt;non-replaced-exts&lt;/code&gt; exists and defaults to &lt;code&gt;default-non-replaced-exts&lt;/code&gt; but the function body never uses &lt;code&gt;non-replaced-exts&lt;/code&gt;: it has &lt;code&gt;default-non-replaced-exts&lt;/code&gt; hardcoded.&lt;/p&gt;
&lt;p&gt;A new feature in the next version of &lt;code&gt;deps-new&lt;/code&gt; depends on this working correctly.&lt;/p&gt;
</description>
<category>tools.build</category>
<guid isPermaLink="true">https://ask.clojure.org/index.php/15208/tools-build-copy-task-does-not-respect-non-replaced-exts</guid>
<pubDate>Sun, 02 Aug 2026 15:39:16 +0000</pubDate>
</item>
<item>
<title>`(nth nil 10)` returns `nil` when it should throw</title>
<link>https://ask.clojure.org/index.php/15195/nth-nil-10-returns-nil-when-it-should-throw</link>
<description>&lt;p&gt;The doc string for &lt;code&gt;nth&lt;/code&gt; reads:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;clojure.core/nth &lt;br&gt;
([coll index] [coll index not-found]) &lt;br&gt;
Returns the&lt;br&gt;
value at the index. get returns nil if index out of   bounds, nth&lt;br&gt;
throws an exception unless not-found is supplied.  nth   also works&lt;br&gt;
for strings, Java arrays, regex Matchers and Lists, and,   in O(n)&lt;br&gt;
time, for sequences.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The behavior agrees when the &lt;code&gt;coll&lt;/code&gt; is &lt;code&gt;[]&lt;/code&gt; or &lt;code&gt;'()&lt;/code&gt; or other empty collections. However:&lt;/p&gt;
&lt;p&gt; &lt;code&gt;user=&amp;gt; (nth [] 10)
Execution error (IndexOutOfBoundsException) at user/eval280 (REPL:1).
null
user=&amp;gt; (nth nil 10)
nil&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Trying to get the 10th item of &lt;code&gt;[]&lt;/code&gt; throws but trying to get the 10th item of &lt;code&gt;nil&lt;/code&gt; returns &lt;code&gt;nil&lt;/code&gt;.&lt;/p&gt;
</description>
<category>Collections</category>
<guid isPermaLink="true">https://ask.clojure.org/index.php/15195/nth-nil-10-returns-nil-when-it-should-throw</guid>
<pubDate>Wed, 22 Jul 2026 03:30:47 +0000</pubDate>
</item>
<item>
<title>Concurrency bug in tools.deps use of Aether/Maven libs?</title>
<link>https://ask.clojure.org/index.php/15192/concurrency-bug-in-tools-deps-use-of-aether-maven-libs</link>
<description>&lt;p&gt;Occasionally, I've been seeing this error:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;[org.eclipse.aether.internal.impl.DefaultTrackingFileManager] [] {} Failed to read tracking file '/home/sean/.m2/repository/org/apache/maven/maven/3.8.8/_remote.repositories'
java.nio.channels.ClosedChannelException&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;which leads to&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Expected HashMap$TreeNode, but was given HashMap$Node, at java.util.HashMap$TreeNode/moveRootToFront (HashMap.java:2020) - runtime error (unexpected type).&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;And the only solution seems to be to blow away part of the &lt;code&gt;~/.m2/repository&lt;/code&gt; and use &lt;code&gt;-Sforce&lt;/code&gt; to recompute/redownload.&lt;/p&gt;
&lt;p&gt;Any idea what might cause this sort of error? (Windows/WSL2, Ubuntu 20.04, all the very latest CLI/Clojure etc). See Slack thread for more discussion: &lt;a rel=&quot;nofollow&quot; href=&quot;https://clojurians.slack.com/archives/C6QH853H8/p1784653752175769&quot;&gt;https://clojurians.slack.com/archives/C6QH853H8/p1784653752175769&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;More of the stacktrace:&lt;br&gt;
&lt;code&gt;`&lt;/code&gt;&lt;br&gt;
at java.base/sun.nio.ch.FileChannelImpl.ensureOpen(FileChannelImpl.java:169)&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    at java.base/sun.nio.ch.FileChannelImpl.lock(FileChannelImpl.java:1676)
    at org.eclipse.aether.internal.impl.DefaultTrackingFileManager.fileLock(DefaultTrackingFileManager.java:171)
    at org.eclipse.aether.internal.impl.DefaultTrackingFileManager.read(DefaultTrackingFileManager.java:65)
    at org.eclipse.aether.internal.impl.EnhancedLocalRepositoryManager.readRepos(EnhancedLocalRepositoryManager.java:220)
    at org.eclipse.aether.internal.impl.EnhancedLocalRepositoryManager.checkFind(EnhancedLocalRepositoryManager.java:151)
    at org.eclipse.aether.internal.impl.EnhancedLocalRepositoryManager.find(EnhancedLocalRepositoryManager.java:128)
    at org.eclipse.aether.internal.impl.DefaultArtifactResolver.resolve(DefaultArtifactResolver.java:360)
    at org.eclipse.aether.internal.impl.DefaultArtifactResolver.resolveArtifacts(DefaultArtifactResolver.java:261)
    at org.eclipse.aether.internal.impl.DefaultArtifactResolver.resolveArtifact(DefaultArtifactResolver.java:243)
    at org.apache.maven.repository.internal.DefaultModelResolver.resolveModel(DefaultModelResolver.java:158)
    at org.apache.maven.repository.internal.DefaultModelResolver.resolveModel(DefaultModelResolver.java:204)
    at org.apache.maven.model.building.DefaultModelBuilder.readParentExternally(DefaultModelBuilder.java:1035)
    at org.apache.maven.model.building.DefaultModelBuilder.readParent(DefaultModelBuilder.java:827)
    at org.apache.maven.model.building.DefaultModelBuilder.build(DefaultModelBuilder.java:336)
    at org.apache.maven.model.building.DefaultModelBuilder.build(DefaultModelBuilder.java:248)
    at org.apache.maven.repository.internal.DefaultArtifactDescriptorReader.loadPom(DefaultArtifactDescriptorReader.java:293)
    at org.apache.maven.repository.internal.DefaultArtifactDescriptorReader.readArtifactDescriptor(DefaultArtifactDescriptorReader.java:183)
    at org.eclipse.aether.internal.impl.DefaultRepositorySystem.readArtifactDescriptor(DefaultRepositorySystem.java:269)
    at clojure.tools.deps.extensions.maven$read_descriptor.invokeStatic(maven.clj:117)
    at clojure.tools.deps.extensions.maven$read_descriptor.invoke(maven.clj:108)
    at clojure.tools.deps.extensions.maven$eval61086$fn__61087.invoke(maven.clj:148)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;`&lt;/code&gt;&lt;/p&gt;
</description>
<category>tools.deps</category>
<guid isPermaLink="true">https://ask.clojure.org/index.php/15192/concurrency-bug-in-tools-deps-use-of-aether-maven-libs</guid>
<pubDate>Tue, 21 Jul 2026 18:08:46 +0000</pubDate>
</item>
<item>
<title>JVM-parity bug in how :clojure.datafy/class is set in clojureCLR</title>
<link>https://ask.clojure.org/index.php/15191/jvm-parity-bug-in-how-clojure-datafy-class-is-set-clojureclr</link>
<description>&lt;p&gt;As I was working on the &lt;code&gt;magic&lt;/code&gt; compiler (the compiler to build to il2cpp in Unity), I noticed i was not having the same behaviour for datafy than clojureCLR.&lt;/p&gt;
&lt;p&gt;In fact, we found a small JVM-parity bug in &lt;code&gt;clojure.datafy/datafy&lt;/code&gt;, in how &lt;code&gt;:clojure.datafy/class&lt;/code&gt; is set in ClojureCLR:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;;; JVM clojure (datafy.clj) : fully qualified name, e.g. my.ns.CombinationB
(vary-meta v assoc ::obj x ::class (-&amp;gt; x class .getName symbol))

;; MAGIC's port : .FullName is the CLR equivalent of .getName, so same result
(vary-meta v assoc ::obj x ::class (-&amp;gt; x class .FullName symbol))

;; ClojureCLR (Clojure.Source/clojure/datafy.clj) : .Name is only the short name,
;; e.g. CombinationB, so the namespace is lost
(vary-meta v assoc ::obj x ::class (-&amp;gt; x class .Name symbol))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This breaks code that resolves the class back from the metadata (e.g. reconstructing records from datafied data ). The fix is small change: &lt;code&gt;.Name&lt;/code&gt; → &lt;code&gt;.FullName&lt;/code&gt;.&lt;/p&gt;
</description>
<category>ClojureCLR</category>
<guid isPermaLink="true">https://ask.clojure.org/index.php/15191/jvm-parity-bug-in-how-clojure-datafy-class-is-set-clojureclr</guid>
<pubDate>Tue, 21 Jul 2026 06:27:09 +0000</pubDate>
</item>
<item>
<title>Implement ^:async (CLJS) for protocol functions and multi-methods</title>
<link>https://ask.clojure.org/index.php/15187/implement-async-cljs-for-protocol-functions-multi-methods</link>
<description>&lt;p&gt;In ClojureScript (as of &lt;code&gt;1.12.145&lt;/code&gt;) one can declare a function (&lt;code&gt;defn&lt;/code&gt;, &lt;code&gt;fn&lt;/code&gt;) to be async by adding the metadata &lt;code&gt;^:async&lt;/code&gt;. However, the same is not applicable to protocol functions and multi-methods. Since async is an invocation semantic, should it be carried over to protocol functions and multimethods? (If yes, should it apply to the protocol definition in &lt;code&gt;defprotocol&lt;/code&gt; or to the protocol implementation in &lt;code&gt;reify&lt;/code&gt;?)&lt;/p&gt;
&lt;p&gt;If async is not to be allowed in protocol functions and multimethods, then the documentation should clearly mention the omissions, alternatives and workaround.&lt;/p&gt;
</description>
<category>ClojureScript</category>
<guid isPermaLink="true">https://ask.clojure.org/index.php/15187/implement-async-cljs-for-protocol-functions-multi-methods</guid>
<pubDate>Sun, 19 Jul 2026 11:53:45 +0000</pubDate>
</item>
<item>
<title>Add assoc-some for constructing maps while skipping nil values</title>
<link>https://ask.clojure.org/index.php/15184/add-assoc-some-for-constructing-maps-while-skipping-values</link>
<description>&lt;p&gt;On latest Clojure alpha, we added :keys! (and :syms!/:strs!) check for key presence. They do not check the value (by design). So a map can have the key, with a nil value, and still pass the check:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(let [{:keys! [a]} {:a nil}]
  a)
;; =&amp;gt; nil
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Sometimes nil is not a valid value for a given key. In those cases, a programmer may want to avoid adding the key at all, rather than adding it with nil. This is the most common idiom today:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(cond-&amp;gt; m
  (some? v) (assoc k v))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A dedicated &lt;code&gt;assoc-some&lt;/code&gt; function would help. It skips the key when the value is nil:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(assoc-some {:a 1} :b 2)
;; =&amp;gt; {:a 1 :b 2}

(assoc-some {:a 1} :b false)
;; =&amp;gt; {:a 1 :b false}

(assoc-some {:a 1} :b nil :c nil)
;; =&amp;gt; {:a 1}

; f returns nil
(assoc-some {:a 1} :b (f))
;; =&amp;gt; {:a 1}
&lt;/code&gt;&lt;/pre&gt;
</description>
<category>Clojure</category>
<guid isPermaLink="true">https://ask.clojure.org/index.php/15184/add-assoc-some-for-constructing-maps-while-skipping-values</guid>
<pubDate>Fri, 17 Jul 2026 18:23:06 +0000</pubDate>
</item>
<item>
<title>destructuring with :keys! and :or</title>
<link>https://ask.clojure.org/index.php/15179/destructuring-with-keys-and-or</link>
<description>&lt;p&gt;I'm trying Clojure 1.13.0-alpha4.  I have a problem with :keys! and :or.  The first example works as expected with the old :keys.  The second example gives me a syntax error when I switch to the new :keys!.  The third example works when I avoid the required key in the defaults. &lt;/p&gt;
&lt;pre&gt;&lt;code&gt; (let [{:keys [a] :or {:a 1}} {:a 2}] a)
 ;=&amp;gt; 2
    
(let [{:keys! [a] :or {:a 1}} {:a 2}] a)
Syntax error macroexpanding let at (REPL:1:1).
Can't supply default value for required key: :a

(let [{:keys! [a] :or {:b 1}} {:a 2}] a)
;=&amp;gt; 2
&lt;/code&gt;&lt;/pre&gt;
</description>
<category>Syntax and reader</category>
<guid isPermaLink="true">https://ask.clojure.org/index.php/15179/destructuring-with-keys-and-or</guid>
<pubDate>Tue, 14 Jul 2026 19:52:33 +0000</pubDate>
</item>
<item>
<title>Possible bug in conditional with NaN comparison</title>
<link>https://ask.clojure.org/index.php/15174/possible-bug-in-conditional-with-nan-comparison</link>
<description>&lt;p&gt;I encountered this possible bug while running a property-based test suite in a ClojureCLR project. Given a comparison between NaN in an if expression, it seemingly takes the wrong branch. &lt;/p&gt;
&lt;p&gt;Clojure (CLR)&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;λ cljr
Clojure core loaded in 837 milliseconds.
Starting main
Clojure core loaded in 409 milliseconds.
Clojure 1.12.2
user=&amp;gt; (&amp;lt;= ##NaN ##NaN)
false
user=&amp;gt; (if (&amp;lt;= ##NaN ##NaN) true false)
true
user=&amp;gt; (let [t (&amp;lt;= ##NaN ##NaN)] (if t true false))
false

user=&amp;gt; (&amp;gt;= ##NaN ##NaN)
false
user=&amp;gt; (if (&amp;gt;= ##NaN ##NaN) true false)
true
user=&amp;gt; (let [t (&amp;gt;= ##NaN ##NaN)] (if t true false))
false
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I wasn't able to replicate the issue on Clojure (JVM), C#, or F#.&lt;/p&gt;
&lt;p&gt;Clojure (JVM)&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;λ clj
Clojure 1.12.0
user=&amp;gt; (&amp;lt;= ##NaN ##NaN)
false
user=&amp;gt; (if (&amp;lt;= ##NaN ##NaN) true false)
false
user=&amp;gt; (let [t (&amp;lt;= ##NaN ##NaN)] (if t true false))
false
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;C#&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;using System;
					
public class Program
{
	public static void Main()
	{
		Console.WriteLine(Double.NaN &amp;lt;= Double.NaN);
		if (Double.NaN &amp;lt;= Double.NaN) {
			Console.WriteLine(true);
		} else {
			Console.WriteLine(false);
		}
		var t = Double.NaN &amp;lt;= Double.NaN;
		if (t) {
			Console.WriteLine(true);
		} else {
			Console.WriteLine(false);
		}
	}
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;False&lt;br&gt;
False&lt;br&gt;
False&lt;/p&gt;
&lt;p&gt;F#&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;λ dotnet fsi

&amp;gt; nan &amp;lt;= nan;;                                                                
val it: bool = false

&amp;gt; if (nan &amp;lt;= nan) then true else false;;                          
val it: bool = false

&amp;gt; let t = nan &amp;lt;= nan;;
val t: bool = false

&amp;gt; if t then true else false;;
val it: bool = false
&lt;/code&gt;&lt;/pre&gt;
</description>
<category>ClojureCLR</category>
<guid isPermaLink="true">https://ask.clojure.org/index.php/15174/possible-bug-in-conditional-with-nan-comparison</guid>
<pubDate>Sat, 11 Jul 2026 15:01:23 +0000</pubDate>
</item>
<item>
<title>require yields confusing &quot;namespace ... not found after loading ...&quot; error if masked by empty test file</title>
<link>https://ask.clojure.org/index.php/15173/require-yields-confusing-namespace-found-after-loading-masked</link>
<description>&lt;p&gt;My home.clj was requring chess.llm, neither file had compilation issues, so I found this error below very strange and I couldn't figure it out. &lt;/p&gt;
&lt;pre&gt;&lt;code&gt;user=&amp;gt; (require 'chess.routes.home :reload)                                                                    
2026-07-10 22:09:37,296 [nREPL-session-cedf8a12-a034-475d-a72c-7683c52bca15]
Syntax error compiling at (chess/routes/home.clj:1:1).
namespace 'chess.llm' not found after loading '/chess/llm' 
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I even tried asking AI for help with troubleshooting but it went down the wrong paths looking for circular dependencies. It wasn't until I copied llm.clj to a different file named caca.clj while only updating the ns declaration &quot;chess.llm =&amp;gt; chess.caca&quot; and corresponding requires in my home.clj, that everything loaded correctly.&lt;/p&gt;
&lt;p&gt;It turns out that I had an empty test file test/chess/llm.clj that was somehow messing up the compilation, and removing this empty test file file, or adding a proper ns declaration, solved the issue.&lt;/p&gt;
&lt;p&gt;I'm reporting this because it would help the next Clojure developer if the error message were more indicative of the bad test file, perhaps by including the full file path.&lt;/p&gt;
&lt;p&gt;Here's the AI-generated explanation of this report:&lt;/p&gt;
&lt;h4&gt;Title&lt;/h4&gt;
&lt;p&gt;&lt;code&gt;require&lt;/code&gt; yields confusing &quot;namespace not found after loading&quot; error if masked by empty file earlier in classpath&lt;/p&gt;
&lt;h4&gt;Environment&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Clojure Version:&lt;/strong&gt; 1.11+ / 1.12&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Build Tool:&lt;/strong&gt; Leiningen / Clojure CLI&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Description&lt;/h4&gt;
&lt;p&gt;When attempting to &lt;code&gt;require&lt;/code&gt; a valid Clojure namespace, if a completely empty &lt;code&gt;.clj&lt;/code&gt; file with the exact same relative file path exists earlier in the classpath sequence (for example, in &lt;code&gt;test/&lt;/code&gt; when &lt;code&gt;test/&lt;/code&gt; precedes &lt;code&gt;src/&lt;/code&gt; in the active profile), Clojure throws a misleading error. &lt;/p&gt;
&lt;p&gt;The compiler successfully locates and loads the empty file, but because the file lacks an &lt;code&gt;(ns ...)&lt;/code&gt; declaration, it fails to find the registered namespace in memory. This effectively masks the actual, working source file further down the classpath, resulting in an error message that mistakenly implies the namespace naming is incorrect, rather than indicating a classpath prioritization issue.&lt;/p&gt;
&lt;h4&gt;Steps to Reproduce&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;Create a project layout where &lt;code&gt;test/&lt;/code&gt; takes priority over &lt;code&gt;src/&lt;/code&gt; on the classpath.&lt;/li&gt;
&lt;li&gt;Create a valid file at &lt;code&gt;src/chess/llm.clj&lt;/code&gt; containing:&lt;br&gt;
&lt;code&gt;`&lt;/code&gt;clojure&lt;br&gt;
(ns chess.llm)&lt;br&gt;
(defn call-llm [] :ok)&lt;br&gt;
&lt;code&gt;`&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Create an empty file at &lt;code&gt;test/chess/llm.clj&lt;/code&gt; (size 0 bytes, absolutely no content).&lt;/li&gt;
&lt;li&gt;Launch a REPL and evaluate: &lt;code&gt;(require 'chess.llm)&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h4&gt;Expected Behavior&lt;/h4&gt;
&lt;p&gt;The compiler should either:&lt;br&gt;
1. Skip empty files on the classpath and continue searching subsequent paths for a matching file containing a valid &lt;code&gt;ns&lt;/code&gt; form.&lt;br&gt;
2. Throw a more descriptive lifecycle error indicating &lt;em&gt;which exact file path&lt;/em&gt; was targeted (e.g., &lt;code&gt;namespace 'chess.llm' not found after loading empty file: test/chess/llm.clj&lt;/code&gt;).&lt;/p&gt;
&lt;h4&gt;Actual Behavior&lt;/h4&gt;
&lt;p&gt;The execution fails completely with a vague stack trace:&lt;br&gt;
&lt;code&gt;`&lt;/code&gt;clojure&lt;br&gt;
Caused by: java.lang.Exception: namespace 'chess.llm' not found after loading '/chess/llm'&lt;br&gt;
&lt;code&gt;`&lt;/code&gt;&lt;/p&gt;
</description>
<category>Clojure</category>
<guid isPermaLink="true">https://ask.clojure.org/index.php/15173/require-yields-confusing-namespace-found-after-loading-masked</guid>
<pubDate>Sat, 11 Jul 2026 02:54:34 +0000</pubDate>
</item>
<item>
<title>Additional handling for `&amp;` symbol in map destructuring for :keys/:syms/:strs could be a breaking change.</title>
<link>https://ask.clojure.org/index.php/15171/additional-handling-symbol-destructuring-breaking-change</link>
<description>&lt;p&gt;Before 1.13.0-alpha1:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(let [{:keys [&amp;amp;]} {:&amp;amp; 1}] &amp;amp;)
;; =&amp;gt; 1

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;After:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(let [{:keys [&amp;amp;]} {:&amp;amp; 1}] &amp;amp;)
Syntax error compiling at (REPL:1:1).
Unable to resolve symbol: &amp;amp; in this context
&lt;/code&gt;&lt;/pre&gt;
</description>
<category>Syntax and reader</category>
<guid isPermaLink="true">https://ask.clojure.org/index.php/15171/additional-handling-symbol-destructuring-breaking-change</guid>
<pubDate>Thu, 09 Jul 2026 10:01:25 +0000</pubDate>
</item>
<item>
<title>Browser REPL on different port</title>
<link>https://ask.clojure.org/index.php/15170/browser-repl-on-different-port</link>
<description>&lt;p&gt;Clojurescript's built-in browser REPL is on port 9000 by default but that clashes with ZScaler on my work laptop so I use port 8090 instead. It took a few goes to get it working but now I have it sorted.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;clojure -M -m cljs.main -v -p 8090 -co '{:closure-defines {&quot;clojure.browser.repl.PORT&quot; 8090}}' -c foo.core -r&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;There are some points in the documentation that might benefit from clarification. The &lt;code&gt;-p&lt;/code&gt; flag is not mentioned on &lt;a rel=&quot;nofollow&quot; href=&quot;https://clojurescript.org/reference/repl-and-main&quot;&gt;The REPL and main entry points&lt;/a&gt; but seems to serve the same purpose as :port described on &lt;a rel=&quot;nofollow&quot; href=&quot;https://clojurescript.org/reference/repl-options&quot;&gt;REPL Options&lt;/a&gt; because this also works:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;clojure -M -m cljs.main -v -ro '{:port 8090}' -co '{:closure-defines {&quot;clojure.browser.repl.PORT&quot; 8090}}' -c foo.core -r&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;What is a little bit surprising is that :port is only mentioned under the Node REPL Options section but applies to browser REPLs too.&lt;/p&gt;
&lt;p&gt;Not really a question in all this but I wanted to share this for others who might get stuck.&lt;/p&gt;
&lt;p&gt;Versions for posterity: Clojure CLI version (deps.clj) 1.12.2.1565 on Windows 11 and ClojureScript 1.11.54.&lt;/p&gt;
</description>
<category>ClojureScript</category>
<guid isPermaLink="true">https://ask.clojure.org/index.php/15170/browser-repl-on-different-port</guid>
<pubDate>Wed, 08 Jul 2026 07:16:39 +0000</pubDate>
</item>
<item>
<title>Weird install paths can break linux-install.sh or posix-install.sh scripts</title>
<link>https://ask.clojure.org/index.php/15164/weird-install-paths-break-linux-install-posix-install-scripts</link>
<description>&lt;p&gt;I'm trying to install clojure from the official installer for once, instead of my old &quot;install lein from apt&quot; method -- I wanted the official tool CLIs.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ curl -L -O https://github.com/clojure/brew-install/releases/latest/download/linux-install.sh
(completes)
$ chmod u+x linux-install.sh 
$ ./linux-install.sh --prefix &quot;$HOME/.local&quot;
Downloading and expanding tar
clojure-tools-1.12.5.1654.tar.gz: OK
Installing libs into /home/fgabolde@/.local/lib/clojure
Installing clojure and clj into /home/fgabolde@/.local/bin
sed: -e expression #1, char 25: unknown option to `s'
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Undeterred, I go back to the &lt;a rel=&quot;nofollow&quot; href=&quot;https://clojure.org/guides/install_clojure&quot;&gt;docs&lt;/a&gt; and find a &quot;POSIX&quot; installer. Aha! That must be it. The other installer assumed something about my shell environment and this one must be written to POSIX specs and that will fix everything!&lt;/p&gt;
&lt;p&gt;I download posix-installer.sh, do the same dance, and exactly the same happens.&lt;/p&gt;
&lt;p&gt;At this point I remember that when this machine was provisioned, IT made a typo and my homedir is &lt;code&gt;/home/fgabolde@&lt;/code&gt; for no good reason. This has tripped up other programs before. And indeed, the sed invocations in the install script use &lt;code&gt;@&lt;/code&gt; as a delimiter, so my weird homedir terminates the replacement string early.&lt;/p&gt;
&lt;p&gt;I fixed it by changing the delimiters in the install script and rerunning.&lt;/p&gt;
</description>
<category>Clojure CLI</category>
<guid isPermaLink="true">https://ask.clojure.org/index.php/15164/weird-install-paths-break-linux-install-posix-install-scripts</guid>
<pubDate>Mon, 06 Jul 2026 15:46:10 +0000</pubDate>
</item>
<item>
<title>Will :keys! work with nested maps?</title>
<link>https://ask.clojure.org/index.php/15160/will-keys-work-with-nested-maps</link>
<description>&lt;p&gt;While learning about the new support for checked &lt;code&gt;:keys!&lt;/code&gt;, I came across this test case for nested maps: &lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/clojure/clojure/blob/master/test/clojure/test_clojure/data_structures.clj#L1382-L1390&quot;&gt;https://github.com/clojure/clojure/blob/master/test/clojure/test_clojure/data_structures.clj#L1382-L1390&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I have two questions.&lt;/p&gt;
&lt;p&gt;First, does this test imply that &lt;code&gt;:keys!&lt;/code&gt; will also be supported in nested destructuring?&lt;/p&gt;
&lt;p&gt;Second, I think there may be a small issue with one of the test cases. It checks that the following destructuring throws an exception:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;{a :a {aa :a :as m :keys! [b c &amp;amp; d e]} :b} (dissoc sample-map :c)&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;The test passes, but it's not obvious whether that's because &lt;code&gt;:c&lt;/code&gt; has been removed from the map or because &lt;code&gt;:e&lt;/code&gt; is listed in &lt;code&gt;:keys!&lt;/code&gt; without being present. Since the previous test doesn't include &lt;code&gt;:e&lt;/code&gt;, it's a bit ambiguous which condition is actually being exercised.&lt;/p&gt;
&lt;p&gt;To make the intent clearer, would it make sense to split this into two separate test cases?&lt;/p&gt;
&lt;p&gt;One that removes &lt;code&gt;:c&lt;/code&gt; and uses &lt;code&gt;:keys! [b c &amp;amp; d]&lt;/code&gt;, verifying that the missing required key causes the exception.&lt;br&gt;
Another that keeps &lt;code&gt;:c&lt;/code&gt; but uses &lt;code&gt;:keys! [b c &amp;amp; d e]&lt;/code&gt;, verifying that the non-bound but missing &lt;code&gt;:e&lt;/code&gt; is what triggers the exception.&lt;/p&gt;
</description>
<category>Test</category>
<guid isPermaLink="true">https://ask.clojure.org/index.php/15160/will-keys-work-with-nested-maps</guid>
<pubDate>Mon, 06 Jul 2026 15:20:35 +0000</pubDate>
</item>
<item>
<title>Namespaced map conversion fails when namespace keyword starts with a number</title>
<link>https://ask.clojure.org/index.php/15159/namespaced-conversion-fails-namespace-keyword-starts-number</link>
<description>&lt;p&gt;It looks like Clojure has no problem with either :0 or :0/a, but when used together in a namesapced map it fails during some internal conversion.&lt;/p&gt;
&lt;p&gt;Worst part: it prints back an unreadable form when if I feed it {:0/a :val}&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;user=&amp;gt; :0
:0
user=&amp;gt; :0/a
:0/a
user=&amp;gt; {:0/a :val}
#:0{:a :val}
user=&amp;gt; #:0{:a :val}
Syntax error reading source at (REPL:45:5).
Namespaced map must specify a valid namespace: 0
:a
:val
Syntax error reading source at (REPL:45:13).
Unmatched delimiter: }
&lt;/code&gt;&lt;/pre&gt;
</description>
<category>Clojure</category>
<guid isPermaLink="true">https://ask.clojure.org/index.php/15159/namespaced-conversion-fails-namespace-keyword-starts-number</guid>
<pubDate>Mon, 06 Jul 2026 15:16:32 +0000</pubDate>
</item>
<item>
<title>Possibly avoidable identity call to force instance method on Class literals</title>
<link>https://ask.clojure.org/index.php/15155/possibly-avoidable-identity-force-instance-method-literals</link>
<description>&lt;p&gt;As of Clojure 1.13.0-alpha2, &lt;code&gt;(.method ClassName)&lt;/code&gt; expands to &lt;code&gt;(.method ^Class (identity ClassName))&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;This is to force &lt;code&gt;(.method ClassName)&lt;/code&gt; to always be an instance method. Without this, it would expand to &lt;code&gt;(. ClassName method)&lt;/code&gt;, which may instead be interpreted as a static method.&lt;/p&gt;
&lt;p&gt;For example, &lt;code&gt;(.getMethods String)&lt;/code&gt; expands to &lt;code&gt;(.getMethods ^Class (identity String))&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;This was introduced in these two commits:&lt;br&gt;
- &lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/clojure/clojure/commit/f95175264df36c3d8fe2113aa9af92cda0f2f5c8&quot;&gt;force instance member interpretation of (.method ClassName), e.g. (.getMethods String) works&lt;/a&gt;&lt;br&gt;
- &lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/clojure/clojure/commit/e45046da8f7fef82157b58af54d1ac6de8e31160&quot;&gt;added autohinting to Class in macroexpansion of (.instanceMethodOfClass Classname) calls&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Since then, Clojure has added support for qualified methods which we can use to reliably propagate the tag without any runtime changes. For example, expanding to &lt;code&gt;(Class/.getMethods String)&lt;/code&gt; is now equivalent to &lt;code&gt;(.getMethods ^Class (identity String))&lt;/code&gt; in terms of tag propagation.&lt;/p&gt;
&lt;p&gt;I have a proof-of-concept &lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/frenchy64/clojure/pull/52/changes&quot;&gt;here&lt;/a&gt; that includes disassembled and decompiled output before and after the change. The net effect of using qualified methods in this case under direct linking is a removal of a single method call to &lt;code&gt;identity&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;   3: invokestatic  #20                 // Method clojure/core$identity.invokeStatic:(Ljava/lang/Object;)Ljava/lang/Object;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The effect is more substantial without direct linking (not included in the PR), with &lt;code&gt;clojure.core/identity&lt;/code&gt; also being added to the static initializer.&lt;/p&gt;
&lt;p&gt;I've also experimented with expanding to &lt;code&gt;(. (do String) getMethods)&lt;/code&gt; (see earlier commits in that PR), which seems to also work and might be another approach.&lt;/p&gt;
</description>
<category>Compiler</category>
<guid isPermaLink="true">https://ask.clojure.org/index.php/15155/possibly-avoidable-identity-force-instance-method-literals</guid>
<pubDate>Thu, 02 Jul 2026 23:47:10 +0000</pubDate>
</item>
<item>
<title>error printed using pprint in clojure 1.13.0-alpha1</title>
<link>https://ask.clojure.org/index.php/15153/error-printed-using-pprint-in-clojure-1-13-0-alpha1</link>
<description>&lt;pre&gt;&lt;code&gt;❯ clj -Sdeps '{:deps {org.clojure/clojure {:mvn/version &quot;1.13.0-alpha1&quot;}}}'
Clojure 1.13.0-alpha1
user=&amp;gt; (clojure.pprint/pprint :foo)
Execution error (ClassCastException) at clojure.pprint.proxy$java.io.Writer$IDeref$PrettyFlush$4923d848/flush (REPL:-1).
class clojure.pprint.proxy$java.io.Writer$IDeref$PrettyFlush$4923d848 cannot be cast to class clojure.pprint.PrettyFlush (clojure.pprint.proxy$java.io.Writer$IDeref$PrettyFlush$4923d848 is in unnamed module of loader 'app'; clojure.pprint.PrettyFlush is in unnamed module of loader clojure.lang.DynamicClassLoader @36a58466)
:foo
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;reported by djblue in #clojure-dev&lt;/p&gt;
</description>
<category>Printing</category>
<guid isPermaLink="true">https://ask.clojure.org/index.php/15153/error-printed-using-pprint-in-clojure-1-13-0-alpha1</guid>
<pubDate>Thu, 02 Jul 2026 20:22:36 +0000</pubDate>
</item>
<item>
<title>Syntax-quoted lists can return nil, differs from ClojureScript</title>
<link>https://ask.clojure.org/index.php/15152/syntax-quoted-lists-can-return-differs-from-clojurescript</link>
<description>&lt;p&gt;Syntax quoted lists can return &lt;code&gt;nil&lt;/code&gt; if only empty seqables are spliced into it:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Clojure 1.12.5
user=&amp;gt; `(~@[])
nil
user=&amp;gt; `(~@[] ~@[])
nil
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;However, the implementation then ensures syntax-quoted empty lists are not nil:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Clojure 1.12.5
user=&amp;gt; `()
()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;ClojureScript returns an empty list in these cases:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;`(~@[])
=&amp;gt; ()
`(~@[] ~@[])
=&amp;gt; ()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The expansion of syntax quote itself is not necessarily a problem if it differs between platforms, but here the evaluation of the expansion differs. This can cause macros to behave differently between platforms (e.g., JVM Clojure vs bootstrapped cljs).&lt;/p&gt;
&lt;p&gt;This behavior seems to be present with all versions of Clojure &lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/clojure/clojure/blob/f85444e6f890eb585e598efefdbd84727427e0a4/src/jvm/clojure/lang/LispReader.java#L731&quot;&gt;including 1.0.0&lt;/a&gt;, so perhaps the ship has sailed here. I went searching for an existing issue or documentation and AFAICT only &lt;a rel=&quot;nofollow&quot; href=&quot;https://clojure.atlassian.net/browse/CLJ-1425&quot;&gt;CLJ-1425&lt;/a&gt; mentions this oddity.&lt;/p&gt;
&lt;p&gt;The reference docs for &lt;a rel=&quot;nofollow&quot; href=&quot;https://clojure.org/reference/reader#syntax-quote&quot;&gt;Syntax Quote&lt;/a&gt; also seem to contradict this behavior:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;For Lists/Vectors/Sets/Maps, syntax-quote establishes a template of the corresponding data structure.&lt;/p&gt;
&lt;/blockquote&gt;
</description>
<category>Syntax and reader</category>
<guid isPermaLink="true">https://ask.clojure.org/index.php/15152/syntax-quoted-lists-can-return-differs-from-clojurescript</guid>
<pubDate>Sun, 28 Jun 2026 20:43:55 +0000</pubDate>
</item>
<item>
<title>clj risk of automatic dependency update causing RCE</title>
<link>https://ask.clojure.org/index.php/15140/clj-risk-of-automatic-dependency-update-causing-rce</link>
<description>&lt;p&gt;I think we should consider enforcing some mechanism to prevent automatic, ai-induced dependency downloading to enable abusers to cause automatic execution of arbitrary code any time a user of AI updates any dependency graph.&lt;/p&gt;
&lt;p&gt;NPM is currently getting abused frequently via this vector.&lt;/p&gt;
&lt;p&gt;NPM has the unfortunate aspect that when you run &lt;code&gt;npm install&lt;/code&gt; it will enable code execution of code provided by a third-party.&lt;/p&gt;
&lt;p&gt;In the age of AI, a hacker could pose as a library useful for something, and do remote code execution via the ability to do something seemingly innocuous and very common in a workplace environment.&lt;/p&gt;
&lt;p&gt;Corporate sabotagists could easily take advantage of this mechanism of compromise and infiltrate common corporate environments.&lt;/p&gt;
</description>
<category>Clojure CLI</category>
<guid isPermaLink="true">https://ask.clojure.org/index.php/15140/clj-risk-of-automatic-dependency-update-causing-rce</guid>
<pubDate>Tue, 16 Jun 2026 08:16:29 +0000</pubDate>
</item>
<item>
<title>Why is aset at least 25 times faster than aset-long?</title>
<link>https://ask.clojure.org/index.php/15138/why-is-aset-at-least-25-times-faster-than-aset-long</link>
<description>&lt;p&gt;Working with primitive long arrays, we discovered that &lt;code&gt;aset-long&lt;/code&gt; is around 25 times slower than &lt;code&gt;aset&lt;/code&gt;, when called statically.  Presumably this is because of the inline path for &lt;code&gt;aset&lt;/code&gt;. Having a specialised &lt;code&gt;aset-long&lt;/code&gt;implies, to me at least, that the specialised version is going to be faster. I'm inferring that &lt;code&gt;aset-lobg&lt;/code&gt; was added for improved performance when invoked through a higher order funciton.  Would adding an :inline to &lt;code&gt;aset-long&lt;/code&gt; et al be considered? or at least a doc string update to warn about the lower performance?&lt;/p&gt;
&lt;p&gt;There is an existing issue for this &lt;a rel=&quot;nofollow&quot; href=&quot;https://clojure.atlassian.net/browse/CLJ-2840&quot;&gt;https://clojure.atlassian.net/browse/CLJ-2840&lt;/a&gt;&lt;/p&gt;
</description>
<category>Clojure</category>
<guid isPermaLink="true">https://ask.clojure.org/index.php/15138/why-is-aset-at-least-25-times-faster-than-aset-long</guid>
<pubDate>Mon, 15 Jun 2026 13:19:24 +0000</pubDate>
</item>
<item>
<title>Why do literal vectors ignore type hinting?</title>
<link>https://ask.clojure.org/index.php/15136/why-do-literal-vectors-ignore-type-hinting</link>
<description>&lt;p&gt;When calling a method on an instance of a Java class that takes a &lt;code&gt;Collection&amp;lt;? extends Something&amp;gt;&lt;/code&gt; as the argument, I've tried the following:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(.theMethod ^SomeClass inst ^Collection [thing1 thing2])
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Unfortunately, when I'm using &lt;code&gt;lein check&lt;/code&gt; this gives me a reflection warning of:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;call to method theMethod on example.SomeClass can't be resolved (argument types: clojure.lang.IPersistentVector).
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I can fix this by binding it to a symbol with a type hint:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(let [^Collection things [thing1 thing2]]
  (.theMethod ^SomeClass inst things))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;What is going on that the literal vector can't be type-hinted in place?&lt;/p&gt;
</description>
<category>Clojure</category>
<guid isPermaLink="true">https://ask.clojure.org/index.php/15136/why-do-literal-vectors-ignore-type-hinting</guid>
<pubDate>Fri, 12 Jun 2026 21:57:51 +0000</pubDate>
</item>
<item>
<title>how to run a clojurescript repl</title>
<link>https://ask.clojure.org/index.php/15134/how-to-run-a-clojurescript-repl</link>
<description>&lt;p&gt;I've used planck occasionally for years, but now it seems to be deprecated. (Won't build on homebrew.) But it sounds like its functionality has been absorbed by clj. So where can I find documentation about this, and how to run a cljs REPL?&lt;/p&gt;
</description>
<category>ClojureScript</category>
<guid isPermaLink="true">https://ask.clojure.org/index.php/15134/how-to-run-a-clojurescript-repl</guid>
<pubDate>Fri, 12 Jun 2026 19:52:36 +0000</pubDate>
</item>
<item>
<title>Consider including a built-in wrapper around `java.net.http.HttpClient` in future versions of Clojure</title>
<link>https://ask.clojure.org/index.php/15129/consider-including-wrapper-around-httpclient-versions-clojure</link>
<description>&lt;p&gt;Java 9 introduced &lt;code&gt;java.net.http.HttpClient&lt;/code&gt;[1] with support for HTTP/1.1, HTTP/2 as well as WebSocket along with other features. It was later standardized in Java 11[2] and has become one of the top picks for Java programs. The latest version of the HTTP client shipped with Java 26 also added support for HTTP/3.[3] &lt;/p&gt;
&lt;p&gt;It would be nice for future versions of Clojure that are based on Java 11+ to include a new namespace with wrapper functions around &lt;code&gt;java.net.http.HttpClient&lt;/code&gt; to make it easier (without all the OOP ceremonies) to work with HTTP in Clojure programs out of the box without relying on any 3rd-party libraries.&lt;/p&gt;
&lt;p&gt;Examples of prior art:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/gnarroway/hato&quot;&gt;https://github.com/gnarroway/hato&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/schmee/java-http-clj&quot;&gt;https://github.com/schmee/java-http-clj&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/babashka/http-client&quot;&gt;https://github.com/babashka/http-client&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://central.sonatype.com/artifact/com.cognitect/http-client&quot;&gt;https://central.sonatype.com/artifact/com.cognitect/http-client&lt;/a&gt;&lt;br&gt;
(upcoming?)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;[1] &lt;a rel=&quot;nofollow&quot; href=&quot;https://openjdk.org/jeps/110&quot;&gt;https://openjdk.org/jeps/110&lt;/a&gt;&lt;br&gt;
[2] &lt;a rel=&quot;nofollow&quot; href=&quot;https://openjdk.org/jeps/321&quot;&gt;https://openjdk.org/jeps/321&lt;/a&gt;&lt;br&gt;
[3] &lt;a rel=&quot;nofollow&quot; href=&quot;https://openjdk.org/jeps/517&quot;&gt;https://openjdk.org/jeps/517&lt;/a&gt;&lt;/p&gt;
</description>
<category>Java Interop</category>
<guid isPermaLink="true">https://ask.clojure.org/index.php/15129/consider-including-wrapper-around-httpclient-versions-clojure</guid>
<pubDate>Mon, 08 Jun 2026 01:37:14 +0000</pubDate>
</item>
<item>
<title>Object.clone() confusion</title>
<link>https://ask.clojure.org/index.php/15125/object-clone-confusion</link>
<description>&lt;p&gt;Consider the following function:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(defn clone [x] 
  (try (.clone x) 
  (catch CloneNotSupportedException _ ...)))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If the arg implements &lt;code&gt;Cloneable&lt;/code&gt;, it works, but the call is reflective. If it doesn't, then it fails with &lt;code&gt;java.lang.IllegalArgumentException: No matching field clone for class ...&lt;/code&gt;. &lt;/p&gt;
&lt;p&gt;I can get it to work by catching &lt;code&gt;Exception&lt;/code&gt; instead, but it feels wrong :(&lt;/p&gt;
&lt;p&gt;Any suggestions? &lt;/p&gt;
</description>
<category>Clojure</category>
<guid isPermaLink="true">https://ask.clojure.org/index.php/15125/object-clone-confusion</guid>
<pubDate>Fri, 05 Jun 2026 21:58:46 +0000</pubDate>
</item>
<item>
<title>Changing type tags can lead to cryptic errors</title>
<link>https://ask.clojure.org/index.php/15124/changing-type-tags-can-lead-to-cryptic-errors</link>
<description>&lt;p&gt;Reporting this as an example of a particularly cryptic error message. Admittedly not the most common thing, but when doing REPL-driven dev with code that uses primitive type tags it can happen.&lt;/p&gt;
&lt;p&gt;The issue here as I understand it is that &lt;code&gt;IFn&lt;/code&gt; contains a few hundred interfaces with some permutation of primitive input and output types, with names like &lt;code&gt;LLO&lt;/code&gt; and &lt;code&gt;ODOL&lt;/code&gt;. Functions that call this are compiled to call the primitive interface to avoid boxing,rather than the generic IFn. If the function is then redefined without or with different primitive tags, then the compiled calling code is no longer calling the right interface.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(defn foo ^long [^long x]
  x)

(defn bar []
  (+ (foo 3) (foo 4)))

(bar)

(defn foo [x] x)

(bar) ;;=&amp;gt; throws: class my.ns$foo cannot be cast to class  clojure.lang.IFn$LL
&lt;/code&gt;&lt;/pre&gt;
</description>
<category>Compiler</category>
<guid isPermaLink="true">https://ask.clojure.org/index.php/15124/changing-type-tags-can-lead-to-cryptic-errors</guid>
<pubDate>Fri, 05 Jun 2026 08:03:00 +0000</pubDate>
</item>
<item>
<title>Request: allow a user function to be specified as the target of clojure.main/report-error</title>
<link>https://ask.clojure.org/index.php/15120/request-allow-function-specified-target-clojure-report-error</link>
<description>&lt;p&gt;The three current targets (&lt;code&gt;file&lt;/code&gt;, &lt;code&gt;none&lt;/code&gt;, &lt;code&gt;stderr&lt;/code&gt;) all serialize all of the error data to a string. During development, it would be convenient to be able to define a function that is called with the exception instance. This function might capture additional application state, or open a window in the user's editor, etc.&lt;/p&gt;
&lt;p&gt;Note that it is not possible to work around this by replacing &lt;code&gt;report-error&lt;/code&gt; itself because the entire clojure.main namespace is AOT-compiled, so &lt;code&gt;alter-var-root&lt;/code&gt; has no effect.&lt;/p&gt;
&lt;p&gt;See &lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/clojure-emacs/cider/issues/3850&quot;&gt;https://github.com/clojure-emacs/cider/issues/3850&lt;/a&gt; for an example where this feature would be helpful.&lt;/p&gt;
&lt;p&gt;Related Slack thread: &lt;a rel=&quot;nofollow&quot; href=&quot;https://clojurians.slack.com/archives/C03S1KBA2/p1779991120304049&quot;&gt;https://clojurians.slack.com/archives/C03S1KBA2/p1779991120304049&lt;/a&gt;&lt;/p&gt;
</description>
<category>Clojure</category>
<guid isPermaLink="true">https://ask.clojure.org/index.php/15120/request-allow-function-specified-target-clojure-report-error</guid>
<pubDate>Tue, 02 Jun 2026 23:53:32 +0000</pubDate>
</item>
<item>
<title>`eval` using functions with metadata</title>
<link>https://ask.clojure.org/index.php/15115/eval-using-functions-with-metadata</link>
<description>&lt;p&gt;TIL:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(eval (list + 1 2)) ; works
(eval (list (var-get #'+) 1 2)) ; works
(eval (list (fn [a b] (+ a b)) 1 2)) ; works

(defmacro m [] `(~(fn [a b] (+ a b)) 1 2))
(m) ; also works

;; however, if the function has any metadata:
(eval (list (with-meta + {}) 1 2))
;; ^ fails, No matching ctor found for class clojure.lang.AFunction$1
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This was unintuitive to discover.&lt;/p&gt;
&lt;p&gt;I solved it locally with a little helper:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(defn val-&amp;gt;expr [v]
  (if (symbol? v)
    `'~v
    (cond-&amp;gt; v
      (and (fn? v) (not (nil? (meta v))))
      (-&amp;gt; (with-meta nil)
          (list (-&amp;gt; v meta (update-vals val-&amp;gt;expr)))
          (conj `with-meta)))))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But this takes special handling. I wonder if something similar would not be possible on a &quot;matching ctor&quot;-level, possibly also for &lt;code&gt;comp&lt;/code&gt;, &lt;code&gt;every-pred?&lt;/code&gt;, etc. It would be fairly trivial even in userland to have versions of these functions which carry metadata sufficient to recreate expressions, e.g. &lt;code&gt;comp&lt;/code&gt; storing the list of functions, and then &lt;code&gt;eval&lt;/code&gt;, on encountering &lt;code&gt;No matching ctor found for class clojure.core$comp$fn__5921&lt;/code&gt;, can instead pull out the list of functions from that value and evaluate &lt;code&gt;(list* comp (:composed-fns (meta v)))&lt;/code&gt; (or some such) instead.&lt;/p&gt;
&lt;p&gt;I think this would be great to have in the core lib, at least for metadata and core libs functions like &lt;code&gt;comp&lt;/code&gt;, &lt;code&gt;some-fn&lt;/code&gt;, &lt;code&gt;every-pred?&lt;/code&gt;, and &lt;code&gt;complement&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Note, I'm not talking about adding or changing ctors for these necessarily. A hook for taking unconstructable values and making a constructable value out of them would serve just as well, maybe even a multifn.&lt;/p&gt;
&lt;p&gt;Strictly in userland and without core lib support, I suppose the cleanest way to do something like this is a custom protocol and probably monkeypatch some core libs functions (maybe &lt;code&gt;eval&lt;/code&gt;?)&lt;/p&gt;
&lt;p&gt;So I suppose my questions are:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Is this something you agree would be good to have in general? Or is this by design for some reason I can't see?&lt;/li&gt;
&lt;li&gt;Would this be good and practical to have in the corelib? Oughtn't be a breaking change at least&lt;/li&gt;
&lt;li&gt;If no, is there currently any sane way to apply my solution in a more systemic way than wrapping every relevant value with a &lt;code&gt;val-&amp;gt;expr&lt;/code&gt; call?&lt;/li&gt;
&lt;/ol&gt;
</description>
<category>Syntax and reader</category>
<guid isPermaLink="true">https://ask.clojure.org/index.php/15115/eval-using-functions-with-metadata</guid>
<pubDate>Mon, 01 Jun 2026 14:33:00 +0000</pubDate>
</item>
<item>
<title>Should reduce-kv support String?</title>
<link>https://ask.clojure.org/index.php/15109/should-reduce-kv-support-string</link>
<description>&lt;p&gt;I like to use &lt;code&gt;reduce-kv&lt;/code&gt; on vectors, where the k is the index and the v is the k-th element of the vector.  IMHO, it would be convenient if &lt;code&gt;reduce-kv&lt;/code&gt; could also work directly on a String.  However, IKVReduce isn't implemented for String so that fails.  You can use &lt;code&gt;(vec &quot;my-string&quot;)&lt;/code&gt; as a work-around, but maybe suffer a bit on performance. &lt;/p&gt;
&lt;p&gt;I think something like this would work:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(extend-protocol clojure.core.protocols/IKVReduce
java.lang.String
(kv-reduce [^String s f init]
  (let [cnt (.length s)]
    (loop [i 0 res init]
      (if (&amp;lt; i cnt)
        (let [ret (f res i (.charAt s i))]
          (if (reduced? ret)
            @ret
            (recur (unchecked-inc i) ret)))
        res)))))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;However, the guidelines say I shouldn't extend a protocol that I don't own to a type that I don't own.&lt;/p&gt;
&lt;p&gt;By the way, &lt;code&gt;(reduce conj [] &quot;Foobar&quot;)&lt;/code&gt; works as you would expect because String implements &lt;code&gt;clojure.core.protocols/InternalReduce&lt;/code&gt; so maybe that's a good precedent.&lt;/p&gt;
</description>
<category>Protocols</category>
<guid isPermaLink="true">https://ask.clojure.org/index.php/15109/should-reduce-kv-support-string</guid>
<pubDate>Fri, 29 May 2026 20:42:43 +0000</pubDate>
</item>
<item>
<title>Consider allowing passing two arguments to sets used as functions</title>
<link>https://ask.clojure.org/index.php/15104/consider-allowing-passing-two-arguments-sets-used-functions</link>
<description>&lt;p&gt;Similar to how &lt;code&gt;get&lt;/code&gt; works with the 3rd &lt;code&gt;not-found&lt;/code&gt; argument.&lt;/p&gt;
&lt;p&gt;It already works in CLJS:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ClojureScript 1.12.116
cljs.user=&amp;gt; (#{:a} :b :c)
:c
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In Clojure, it errors out:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Clojure 1.12.0
user=&amp;gt; (#{:a} :b :c)
Execution error (ArityException) at user/eval1 (REPL:1).
Wrong number of args (2) passed to: clojure.lang.PersistentHashSet
&lt;/code&gt;&lt;/pre&gt;
</description>
<category>Clojure</category>
<guid isPermaLink="true">https://ask.clojure.org/index.php/15104/consider-allowing-passing-two-arguments-sets-used-functions</guid>
<pubDate>Tue, 26 May 2026 13:44:16 +0000</pubDate>
</item>
<item>
<title>The behavior of `filter` on infinite sequences in Transducers</title>
<link>https://ask.clojure.org/index.php/15095/the-behavior-of-filter-on-infinite-sequences-in-transducers</link>
<description>&lt;p&gt;Could you tell me where I can find information understanding the difference in behavior below?&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;user=&amp;gt; (clojure-version)
&quot;1.12.5&quot;
user=&amp;gt; (def iter1 (eduction (filter even?) (range)))
#'user/iter1
user=&amp;gt; (def iter2 (eduction (filter zero?) (range)))
#'user/iter2
user=&amp;gt; (take 1 iter1)
(0)
user=&amp;gt; (take 1 iter2)
;;; Pressed Ctrl-C due to no response
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This behavior occurs when the input source is infinite, but I'm confused because I think &lt;code&gt;filter&lt;/code&gt; is stateless. Of course, it works fine when Transducers aren't used.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;user=&amp;gt; (take 1 (filter even? (range)))
(0)
user=&amp;gt; (take 1 (filter zero? (range)))
(0)
&lt;/code&gt;&lt;/pre&gt;
</description>
<category>Transducers</category>
<guid isPermaLink="true">https://ask.clojure.org/index.php/15095/the-behavior-of-filter-on-infinite-sequences-in-transducers</guid>
<pubDate>Sun, 24 May 2026 05:38:39 +0000</pubDate>
</item>
<item>
<title>gitlibs/tags throws a NPE if the repository has no tags</title>
<link>https://ask.clojure.org/index.php/15094/gitlibs-tags-throws-a-npe-if-the-repository-has-no-tags</link>
<description>&lt;p&gt;Using:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;org.clojure/tools.gitlibs     {:mvn/version &quot;2.6.212&quot;}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This throws NPE&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(gitlibs/tags &quot;https://github.com/clojure/clojure-site.git&quot;)
&lt;/code&gt;&lt;/pre&gt;
</description>
<category>Tools</category>
<guid isPermaLink="true">https://ask.clojure.org/index.php/15094/gitlibs-tags-throws-a-npe-if-the-repository-has-no-tags</guid>
<pubDate>Fri, 22 May 2026 15:59:50 +0000</pubDate>
</item>
<item>
<title>Can clojure builds be reproducible? (new Debian forky requirement)</title>
<link>https://ask.clojure.org/index.php/15083/can-clojure-builds-reproducible-debian-forky-requirement</link>
<description>&lt;p&gt;Debian now requires packages to be reproducible: &lt;a rel=&quot;nofollow&quot; href=&quot;https://lists.debian.org/debian-devel-announce/2026/05/msg00001.html&quot;&gt;https://lists.debian.org/debian-devel-announce/2026/05/msg00001.html&lt;/a&gt; and I thought I recalled that compilation, at least, couldn't produce reproducible output (e.g. with respect to variable naming in the class files), and some testing suggests that might still be the case (tested with 1.12.0 via &lt;a rel=&quot;nofollow&quot; href=&quot;https://diffoscope.org/&quot;&gt;https://diffoscope.org/&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;I assume that for Clojure related packages to remain in the next Debian release, we'll need to address the requirement one way or another, if we can, so I wanted to ask about the situation upstream first.&lt;/p&gt;
&lt;p&gt;Offhand, I think the main concern is with AOT compilation, which Debian only uses for &quot;leaf&quot; applications, packaged as an uberjar (e.g. leiningen, puppetserver, puppetdb, etc.), and Debian already has infrastructure to make sure that jars are otherwise reproducible (with respect to timestamps, etc.), so the issue there is mostly &quot;just&quot; regarding the file content.&lt;/p&gt;
&lt;p&gt;Thanks&lt;/p&gt;
</description>
<category>Clojure</category>
<guid isPermaLink="true">https://ask.clojure.org/index.php/15083/can-clojure-builds-reproducible-debian-forky-requirement</guid>
<pubDate>Tue, 19 May 2026 18:04:14 +0000</pubDate>
</item>
<item>
<title>core.unify does not preserve want-occurs? in recursive unify-variable calls</title>
<link>https://ask.clojure.org/index.php/15082/core-unify-preserve-occurs-recursive-unify-variable-calls</link>
<description>&lt;p&gt;core.unify does not preserve &lt;code&gt;want-occurs?&lt;/code&gt; when recursing from &lt;code&gt;unify-variable-&lt;/code&gt;. That is, if &lt;code&gt;unify-varable-&lt;/code&gt; calls &lt;code&gt;garner-unifiers&lt;/code&gt;, it does not pass itself as the &lt;code&gt;uv-fn&lt;/code&gt; parameter, so &lt;code&gt;garner-unifiers&lt;/code&gt; will default to &lt;code&gt;unify-variable&lt;/code&gt; (which includes an occurs? check). I'm not sure if this was intentional, but I found it surprising. If not intentional, then I believe calls to &lt;code&gt;garner-unifiers&lt;/code&gt; in &lt;code&gt;create-var-unification-fn&lt;/code&gt; should look like:&lt;br&gt;
&lt;code&gt;(garner-unifiers ~'var-unify ~varp vb# ~expr ~binds)&lt;/code&gt;&lt;/p&gt;
</description>
<category>core.unify</category>
<guid isPermaLink="true">https://ask.clojure.org/index.php/15082/core-unify-preserve-occurs-recursive-unify-variable-calls</guid>
<pubDate>Sat, 16 May 2026 19:09:05 +0000</pubDate>
</item>
<item>
<title>linux installer fails for non english locale</title>
<link>https://ask.clojure.org/index.php/15081/linux-installer-fails-for-non-english-locale</link>
<description>&lt;p&gt;&quot;OK&quot; returned by &lt;code&gt;sha256sum&lt;/code&gt; may be translated. Better rely on the exit status. Since &lt;code&gt;-p pipefail&lt;/code&gt; is used, the pipe to &lt;code&gt;grep&lt;/code&gt; could be simply omitted.&lt;/p&gt;
</description>
<category>Tools</category>
<guid isPermaLink="true">https://ask.clojure.org/index.php/15081/linux-installer-fails-for-non-english-locale</guid>
<pubDate>Thu, 14 May 2026 20:48:19 +0000</pubDate>
</item>
<item>
<title>`(:k m)` returns `nil` while `(identical? (first (keys m)) :k)` is `true` — two coexisting `Keyword` instances?</title>
<link>https://ask.clojure.org/index.php/15073/returns-while-identical-first-coexisting-keyword-instances</link>
<description>&lt;p&gt;We're seeing what looks like a violation of the keyword-interning invariant in production. The bug is deterministic (repeats thousands of times in the same order on the same Aleph/Netty thread) and is cleared by recompiling the affected namespaces via nREPL.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(when (and (map? result) (nil? (:payload result)))   ; this WHEN fires
  (let [payload-key (-&amp;gt;&amp;gt; (keys result)
                         (filter #(.contains (pr-str %) &quot;payload&quot;))
                         first)
        payload-via-key (when payload-key (get result payload-key))]
    (log/warn {:result-type                   (str (type result))
               :result-keys                   (pr-str (keys result))
               :payload-key-equals-literal?   (= payload-key :payload)
               :payload-key-identical?        (identical? payload-key :payload)
               :payload-via-found-key-nil?    (nil? payload-via-key)}
              &quot;diagnostic&quot;)))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Logged values when the bug fires:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;{:result-type                   clojure.lang.PersistentArrayMap
 :result-keys                   (:payload :aws-xray)
 :payload-key-equals-literal?   true
 :payload-key-identical?        true
 :payload-via-found-key-nil?    false}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;(:payload result)&lt;/code&gt; in the &lt;code&gt;when&lt;/code&gt; returned nil.&lt;/li&gt;
&lt;li&gt;A few lines later, the diagnostic body proves that the first key in &lt;code&gt;(keys result)&lt;/code&gt; IS the body-site &lt;code&gt;:payload&lt;/code&gt; literal by identity (and therefore by &lt;code&gt;=&lt;/code&gt;, since &lt;code&gt;Keyword&lt;/code&gt; inherits &lt;code&gt;Object.equals&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;(get result that-key)&lt;/code&gt; returns the actual non-nil payload value.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;PersistentArrayMap.indexOf&lt;/code&gt; uses &lt;code&gt;==&lt;/code&gt; for &lt;code&gt;Keyword&lt;/code&gt; keys, so the only way &lt;code&gt;(:payload result)&lt;/code&gt; returns nil while &lt;code&gt;(keys result)&lt;/code&gt; yields a key that is &lt;code&gt;identical?&lt;/code&gt; to &lt;code&gt;:payload&lt;/code&gt; at a nearby site is if &lt;strong&gt;the &lt;code&gt;:payload&lt;/code&gt; literal at the WHEN site and the &lt;code&gt;:payload&lt;/code&gt; literal at the body site are two different &lt;code&gt;Keyword&lt;/code&gt; instances&lt;/strong&gt;, even though they're written identically in one source-level function.&lt;/p&gt;
&lt;p&gt;We compareed the &lt;code&gt;:payload&lt;/code&gt; literal with the &lt;code&gt;payload-key&lt;/code&gt; and found that both have - &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;identical content hashcode (&lt;code&gt;-383036092&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;identical name bytes &lt;code&gt;[0x70 0x61 0x79 0x6C 0x6F 0x61 0x64]&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;identical codepoints&lt;/li&gt;
&lt;li&gt;same classloader&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;so it really looks like two distinct interned &lt;code&gt;Keyword&lt;/code&gt; instances with the same name.&lt;/p&gt;
&lt;h4&gt;Environment&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Clojure &lt;code&gt;1.12.4&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Eclipse Temurin JDK 25, Shenandoah GC, virtual threads enabled&lt;/li&gt;
&lt;li&gt;ARM64 (AWS Graviton, ECS Fargate)&lt;/li&gt;
&lt;li&gt;Aleph + Netty, transit-clj/transit-java for decoding&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Questions&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;Could this be a bug in JVM / Clojure runtime?&lt;/li&gt;
&lt;li&gt;Has similar behavior been seen in other cases?&lt;/li&gt;
&lt;li&gt;What more evidence could we capture?&lt;/li&gt;
&lt;/ol&gt;
</description>
<category>Clojure</category>
<guid isPermaLink="true">https://ask.clojure.org/index.php/15073/returns-while-identical-first-coexisting-keyword-instances</guid>
<pubDate>Mon, 11 May 2026 12:59:06 +0000</pubDate>
</item>
<item>
<title>Reflection warning when long hint on an argument</title>
<link>https://ask.clojure.org/index.php/15067/reflection-warning-when-long-hint-on-an-argument</link>
<description>&lt;p&gt;Hi,&lt;/p&gt;
&lt;p&gt;I noticed some reflection warning that goes away when &lt;em&gt;removing&lt;/em&gt; a hint from fn arguments. I would like to understand the reason for this.&lt;/p&gt;
&lt;p&gt;Example, loading this code&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(set! *warn-on-reflection* true)

(defn duration-of-seconds
  (^java.time.Duration [^long seconds]
   (java.time.Duration/ofSeconds seconds)))

(defn sleep
  [seconds]
  (Thread/sleep (duration-of-seconds seconds)))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Raises a reflection warning:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;call to static method sleep on java.lang.Thread can't be resolved (argument types: java.lang.Object).
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;However, just removing the &lt;code&gt;^long&lt;/code&gt; hint from the &lt;code&gt;duration-of-seconds&lt;/code&gt; fn argument, makes the reflection warning go away.&lt;/p&gt;
&lt;p&gt;Thanks!&lt;/p&gt;
</description>
<category>Java Interop</category>
<guid isPermaLink="true">https://ask.clojure.org/index.php/15067/reflection-warning-when-long-hint-on-an-argument</guid>
<pubDate>Fri, 01 May 2026 19:49:31 +0000</pubDate>
</item>
<item>
<title>Default implementation of AsElements to treat numbers as numbers, not strings</title>
<link>https://ask.clojure.org/index.php/15060/default-implementation-aselements-numbers-numbers-strings</link>
<description>&lt;p&gt;I'm slowly converting some code from using &lt;code&gt;xml/element&lt;/code&gt; to &lt;code&gt;xml/sexp-as-element&lt;/code&gt;, and I've noticed a discrepancy. &lt;code&gt;xml/element&lt;/code&gt; does (almost) no processing of the &quot;content&quot;, inserting it directly (unless it's &lt;code&gt;nil&lt;/code&gt;). &lt;code&gt;xml/sexp-as-element&lt;/code&gt; calls &lt;code&gt;(str)&lt;/code&gt; on the &quot;content&quot; if it's not seq of some kind (vector or ISeq) or a keyword. This means that &lt;code&gt;(= (xml/element :foo {} 1) (xml/sexp-as-element [:foo 1]))&lt;/code&gt; is false.&lt;/p&gt;
&lt;p&gt;There are probably other differences, but this one seems relatively big, as there's no way to use numbers in &lt;code&gt;xml/sexp-as-element&lt;/code&gt; without calling &lt;code&gt;extend-protocol&lt;/code&gt; yourself.&lt;/p&gt;
&lt;p&gt;May I recommend/request adding this extension? It will make &lt;code&gt;xml/sexp-as-element&lt;/code&gt; match &lt;code&gt;xml/element&lt;/code&gt; for numbers, and make &lt;code&gt;xml/sexp-as-element&lt;/code&gt; match hiccup in general.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(extend-protocol clojure.data.xml.protocols/AsElements
  java.lang.Number
  (as-elements [n] [n]))
&lt;/code&gt;&lt;/pre&gt;
</description>
<category>data.xml</category>
<guid isPermaLink="true">https://ask.clojure.org/index.php/15060/default-implementation-aselements-numbers-numbers-strings</guid>
<pubDate>Tue, 28 Apr 2026 16:10:26 +0000</pubDate>
</item>
<item>
<title>Installing Clojure on IPv6-only machine</title>
<link>https://ask.clojure.org/index.php/15051/installing-clojure-on-ipv6-only-machine</link>
<description>&lt;p&gt;Since GitHub (still) do not support IPv6 it is not possible to follow the instructions at &lt;a rel=&quot;nofollow&quot; href=&quot;https://clojure.org/guides/install_clojure&quot;&gt;https://clojure.org/guides/install_clojure&lt;/a&gt; (for Linux, say) to install the Clojure CLI on a machine running ONLY IPv6 (in this case Hertzner).&lt;/p&gt;
&lt;p&gt;When downloading the .tar.gz-file manally and uploading it directly, installing the CLI tools is possilbe.&lt;/p&gt;
&lt;p&gt;The problems seem to continue installing common clojure dependencies, like data.json 2.5.2, which leads to this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;clj -X:server
Error building classpath. Failed to read artifact descriptor for org.clojure:data.json:jar:2.5.2
org.eclipse.aether.resolution.ArtifactDescriptorException: Failed to read artifact descriptor for org.clojure:data.json:jar:2.5.2
	at org.apache.maven.repository.internal.DefaultArtifactDescriptorReader.loadPom(DefaultArtifactDescriptorReader.java:255)
	at org.apache.maven.repository.internal.DefaultArtifactDescriptorReader.readArtifactDescriptor(DefaultArtifactDescriptorReader.java:171)
	at org.eclipse.aether.internal.impl.DefaultRepositorySystem.readArtifactDescriptor(DefaultRepositorySystem.java:263)
	at clojure.tools.deps.extensions.maven$read_descriptor.invokeStatic(maven.clj:115)
	at clojure.tools.deps.extensions.maven$fn__1340.invokeStatic(maven.clj:143)
	at clojure.tools.deps.extensions.maven$fn__1340.invoke(maven.clj:143)
	at clojure.lang.MultiFn.invoke(MultiFn.java:244)
	at clojure.tools.deps$expand_deps$children_task__959$fn__961$fn__962.invoke(deps.clj:299)
    ...
Caused by: java.net.SocketException: Network is unreachable
at java.base/sun.nio.ch.Net.connect0(Native Method)
at java.base/sun.nio.ch.Net.connect(Net.java:546)
at java.base/sun.nio.ch.Net.connect(Net.java:535)
at java.base/sun.nio.ch.NioSocketImpl.connect(NioSocketImpl.java:585)
at java.base/java.net.SocksSocketImpl.connect(SocksSocketImpl.jar
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;All this seem a bit bisarre of course. Workarounds would make me happy!&lt;/p&gt;
</description>
<category>Tools</category>
<guid isPermaLink="true">https://ask.clojure.org/index.php/15051/installing-clojure-on-ipv6-only-machine</guid>
<pubDate>Fri, 24 Apr 2026 23:21:53 +0000</pubDate>
</item>
<item>
<title>&quot;Nested&quot; vs &quot;lateral&quot; exception causes</title>
<link>https://ask.clojure.org/index.php/15031/nested-vs-lateral-exception-causes</link>
<description>&lt;p&gt;Currently, &lt;code&gt;clojure.core/ex-info&lt;/code&gt; must take a &lt;code&gt;msg&lt;/code&gt; and data &lt;code&gt;map&lt;/code&gt;, and may take a &lt;code&gt;cause&lt;/code&gt;, which must be another &lt;code&gt;Throwable&lt;/code&gt;, which may have its own &lt;code&gt;cause&lt;/code&gt;, etc. etc..&lt;/p&gt;
&lt;p&gt;This supports the case of &quot;nested&quot; exceptions quite well, e.g. in the case of compilation exceptions being caused by macroexpansion exceptions, potentially with their own cause, and works well for fail-on-first-problem situations.&lt;/p&gt;
&lt;p&gt;There's also the situation of &quot;lateral&quot; exceptions, e.g. in the case of test runners or static analysers, which is not supported. In this case, if we take &lt;code&gt;lazytest&lt;/code&gt; as a concrete example, the test runner throws an exception if any of the test cases it runs throws an exception, but the overall cause of the overall exception, conceptually, is &lt;em&gt;all&lt;/em&gt; the individual exceptions.&lt;/p&gt;
&lt;p&gt;Currently, the only to do this is to make some bespoke thing in the data &lt;code&gt;map&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;I propose changing &lt;code&gt;clojure.core/ex-info&lt;/code&gt; to take &lt;code&gt;[msg map &amp;amp; causes]&lt;/code&gt;, which would be a non-breaking change (or, while we're at it, make the &lt;code&gt;map&lt;/code&gt; arg optional as well and default it to &lt;code&gt;{}&lt;/code&gt;, but that's a separate topic).&lt;/p&gt;
&lt;p&gt;That leaves the question of how to handle &lt;code&gt;ex-cause&lt;/code&gt;. To my understanding, to change it to return the cause or the list of causes, would maybe be a breaking change for general exception handling libraries or something, but would not imo pose any significant problem. Alternatively, we might have &lt;code&gt;ex-causes&lt;/code&gt; to always return a list, and change &lt;code&gt;ex-cause&lt;/code&gt; to &lt;code&gt;(comp first ex-causes)&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Any thoughts? I don't trust myself to spearhead a PR alone on this but I'd love to contribute, certainly the pure-clojure side of things seems straightforward enough (and I'd love to patch this into &lt;code&gt;lazytest&lt;/code&gt;, but that's again a different topic).&lt;/p&gt;
</description>
<category>Errors</category>
<guid isPermaLink="true">https://ask.clojure.org/index.php/15031/nested-vs-lateral-exception-causes</guid>
<pubDate>Sun, 05 Apr 2026 14:18:26 +0000</pubDate>
</item>
<item>
<title>Destructuring {:as opts} unexpected behaviour with seq</title>
<link>https://ask.clojure.org/index.php/15028/destructuring-as-opts-unexpected-behaviour-with-seq</link>
<description>&lt;p&gt;Hi,&lt;/p&gt;
&lt;p&gt;I found out something weird in some old code, where I wanted to pass the first map in a sequence and by mistake the code was working while actually passing the sequence itself!&lt;/p&gt;
&lt;p&gt;After digging to make sense of this, I found out it has to do with the &lt;code&gt;{:as opts}&lt;/code&gt; destructuring.&lt;/p&gt;
&lt;p&gt;Here's some code:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;;; even if something is assigned sequential vs associative
;; the `:as` is transparent
(let [[:as opts] {1 2 3 4}]
  opts)
#_=&amp;gt; {1 2, 3 4}
(let [{:as opts} [1 2 3 4]]
  opts)
#_=&amp;gt; [1 2 3 4]
;; however with a seq it's returned as a map
(let [{:as opts} (seq [1 2 3 4])]
  opts)
#_=&amp;gt; {1 2, 3 4}

;; and it only gets weirder!
(let [{:as opts} (seq [{:k :v}])]
  opts)
#_=&amp;gt; {:k :v}
(let [{:as opts} (seq [{:k1 :v1} {:k2 :v2}])]
  opts)
#_=&amp;gt; {{:k1 :v1} {:k2 :v2}}
(let [{:as opts} (seq [{:k1 :v1} {:k2 :v2} {:k3 :v3}])]
  opts)
#_=&amp;gt; {{:k1 :v1} {:k2 :v2}, :k3 :v3}
(let [{:as opts} (seq [{:k1 :v1} {:k2 :v2} :not-a-map])]
  opts)
;; java.lang.IllegalArgumentException: Don't know how to create ISeq from: clojure.lang.Keyword
(let [{:as opts} (seq [1 2 3])]
  opts)
;; java.lang.IllegalArgumentException: Don't know how to create ISeq from: java.lang.Long
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In my case I didn't realize my code was wrong because &lt;code&gt;{:as opts} {:k :v}&lt;/code&gt; is the same as &lt;code&gt;{:as opts} (seq [{:k :v}])&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;To me this is behaviour I would expect closer to &lt;code&gt;&amp;amp; {:as opts}&lt;/code&gt; rather than just plain map destructuring &lt;code&gt;{:as opts}&lt;/code&gt;. Maybe both behaviours should be separated?&lt;/p&gt;
&lt;p&gt;I think this should be tackled either by&lt;br&gt;
1. make &lt;code&gt;:as&lt;/code&gt; transparent regardless of what comes in to always bind&lt;br&gt;
2. throw an error earlier when it's not of the expected destructuring&lt;br&gt;
3. Document this very unexpected edge case in &lt;a rel=&quot;nofollow&quot; href=&quot;https://clojure.org/reference/special_forms#associative-destructuring&quot;&gt;https://clojure.org/reference/special_forms#associative-destructuring&lt;/a&gt;&lt;br&gt;
4. Separate the keyword arguments use case from plain map destructuring? (Assuming both are now mixed together)&lt;/p&gt;
</description>
<category>Sequences</category>
<guid isPermaLink="true">https://ask.clojure.org/index.php/15028/destructuring-as-opts-unexpected-behaviour-with-seq</guid>
<pubDate>Sat, 04 Apr 2026 23:50:39 +0000</pubDate>
</item>
<item>
<title>Optimize `eduction`</title>
<link>https://ask.clojure.org/index.php/15027/optimize-eduction</link>
<description>&lt;h2&gt;Problem statement&lt;/h2&gt;
&lt;p&gt;Eduction is useful part of the transducer ecosystem, which has a benefit/aim of improved performance. However, the function &lt;code&gt;eduction&lt;/code&gt; only has a single varargs arity, which adds multiple function calls and and &lt;code&gt;seq&lt;/code&gt; traversal allocations.&lt;/p&gt;
&lt;p&gt;As seen in &lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/clj-kondo/clj-kondo/pull/2801&quot;&gt;this PR&lt;/a&gt; to clj-kondo, manually passing in an xform directly can improve both overall performance and lower allocations.&lt;/p&gt;
&lt;h2&gt;Proposal&lt;/h2&gt;
&lt;p&gt;Adding arities to &lt;code&gt;eduction&lt;/code&gt; can sidestep those allocations and seq traversals, improving baseline performance of all &lt;code&gt;eduction&lt;/code&gt; invocations.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(defn eduction2
  {:arglists '([xform* coll])
   :added &quot;1.7&quot;}
  ([coll] (-&amp;gt;Eduction identity coll))
  ([f1 coll] (-&amp;gt;Eduction f1 coll))
  ([f1 f2 coll] (-&amp;gt;Eduction (comp f1 f2) coll))
  ([f1 f2 f3 coll] (-&amp;gt;Eduction (comp f1 f2 f3) coll))
  ([f1 f2 f3 f4 &amp;amp; args]
   (-&amp;gt;Eduction (apply comp f1 f2 f3 f4 (butlast args)) (last args))))
&lt;/code&gt;&lt;/pre&gt;
</description>
<category>Transducers</category>
<guid isPermaLink="true">https://ask.clojure.org/index.php/15027/optimize-eduction</guid>
<pubDate>Fri, 03 Apr 2026 14:25:17 +0000</pubDate>
</item>
<item>
<title>Missing protocol error will hang on infinite `(range)` input in ClojureScript but not Clojure</title>
<link>https://ask.clojure.org/index.php/15026/missing-protocol-error-infinite-range-clojurescript-clojure</link>
<description>&lt;p&gt;functions like &lt;code&gt;transient&lt;/code&gt;, &lt;code&gt;assoc&lt;/code&gt;, etc  will throw helpful missing-protocol error when receiving invalid input but it will hang if it receives infinite &lt;code&gt;(range)&lt;/code&gt;.&lt;br&gt;
this is related to issue below&lt;br&gt;
&lt;a rel=&quot;nofollow&quot; href=&quot;https://ask.clojure.org/index.php/14578/even-range-hangs?show=14578#q14578&quot;&gt;https://ask.clojure.org/index.php/14578/even-range-hangs?show=14578#q14578&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;however, missing-protocol only hang in clojurescript but not clojure so I am wondering if this difference is intended.&lt;/p&gt;
&lt;p&gt;example calls that should throws&lt;br&gt;
- &lt;code&gt;(transient (range))&lt;/code&gt;&lt;br&gt;
- &lt;code&gt;(assoc (range) :a 1)&lt;/code&gt;&lt;/p&gt;
</description>
<category>ClojureScript</category>
<guid isPermaLink="true">https://ask.clojure.org/index.php/15026/missing-protocol-error-infinite-range-clojurescript-clojure</guid>
<pubDate>Fri, 03 Apr 2026 11:16:47 +0000</pubDate>
</item>
<item>
<title>requiring an empty .clj without an alias should fail as with an alias</title>
<link>https://ask.clojure.org/index.php/15022/requiring-an-empty-clj-without-alias-should-fail-with-alias</link>
<description>&lt;p&gt;if file a/b/c.clj is &quot;empty&quot;&lt;/p&gt;
&lt;p&gt;it creates an empty ns: (and does not fail) when doing&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(require '[a.b.c])
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;while when using &quot;:as&quot; it fails correctly with error:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(require '[a.b.c] :as c)
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;&lt;p&gt;Syntax error compiling at ... ; namespace 'a.b.c' not&lt;br&gt;
found after loading '/a/b/c'&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;see here for initial discussion:&lt;br&gt;
&lt;a rel=&quot;nofollow&quot; href=&quot;https://clojurians.slack.com/archives/C03S1KBA2/p1775155101843229?thread_ts=1775153939.803389&amp;amp;cid=C03S1KBA2&quot;&gt;https://clojurians.slack.com/archives/C03S1KBA2/p1775155101843229?thread_ts=1775153939.803389&amp;amp;cid=C03S1KBA2&lt;/a&gt;&lt;/p&gt;
</description>
<category>Clojure</category>
<guid isPermaLink="true">https://ask.clojure.org/index.php/15022/requiring-an-empty-clj-without-alias-should-fail-with-alias</guid>
<pubDate>Thu, 02 Apr 2026 18:48:37 +0000</pubDate>
</item>
<item>
<title>Does Clojure have an anti LLM code contributions policy? Would it make sense for Clojure to adopt one?</title>
<link>https://ask.clojure.org/index.php/15004/clojure-contributions-policy-would-make-sense-clojure-adopt</link>
<description>&lt;p&gt;LLM use appears to have a bunch of ethical and practical problems, the most pressing one seems to be the plagiarism that seems to be pretty excessive even for code and even when not baited:&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/mastodon/mastodon/issues/38072#issuecomment-4105681567&quot;&gt;Video clip of apparently a lawyer live demoing what seems to be Co-Pilot plagiasm&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I don't know anything about law, but the lawyer at one point says: &quot;This is a copyright infringement.&quot; I've also found this: &lt;a rel=&quot;nofollow&quot; href=&quot;https://www.twobirds.com/en/insights/2025/landmark-ruling-of-the-munich-regional-court-(gema-v-openai)-on-copyright-and-ai-training&quot;&gt;https://www.twobirds.com/en/insights/2025/landmark-ruling-of-the-munich-regional-court-(gema-v-openai)-on-copyright-and-ai-training&lt;/a&gt; It seems to talk about &quot;fair use&quot; of AI model training.&lt;/p&gt;
&lt;p&gt;Also see this high-profile incident: &lt;a rel=&quot;nofollow&quot; href=&quot;https://www.pcgamer.com/software/ai/microsoft-uses-plagiarized-ai-slop-flowchart-to-explain-how-github-works-removes-it-after-original-creator-calls-it-out-careless-blatantly-amateuristic-and-lacking-any-ambition-to-put-it-gently/&quot;&gt;https://www.pcgamer.com/software/ai/microsoft-uses-plagiarized-ai-slop-flowchart-to-explain-how-github-works-removes-it-after-original-creator-calls-it-out-careless-blatantly-amateuristic-and-lacking-any-ambition-to-put-it-gently/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Also this field study that appears to be putting the plagiarism rate at seemingly at least 2-5%: &lt;a rel=&quot;nofollow&quot; href=&quot;https://dl.acm.org/doi/10.1145/3543507.3583199&quot;&gt;https://dl.acm.org/doi/10.1145/3543507.3583199&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This article mentions a study that apparently puts the plagiarism rate at 8–15% as a minimum for the easily detectable kind: &lt;a rel=&quot;nofollow&quot; href=&quot;https://www.theatlantic.com/technology/2026/01/ai-memorization-research/685552/&quot;&gt;https://www.theatlantic.com/technology/2026/01/ai-memorization-research/685552/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I don't know what this means legally, but at least morally and ethically this seems sad.&lt;/p&gt;
&lt;p&gt;Apparently, some people in the Clojure space already spoke out against LLMs, but I wasn't able to find any anti LLM policy. If there was such a policy, I would expect it to be mentioned in the following places:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://clojure.org/dev/developing_patches&quot;&gt;https://clojure.org/dev/developing_patches&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://clojure.org/community/contributing&quot;&gt;https://clojure.org/community/contributing&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;I simply wanted to suggest that perhaps the project may want to adopt such a policy.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Here are some other projects that have already done so: &lt;a rel=&quot;nofollow&quot; href=&quot;https://asahilinux.org/docs/project/policies/slop/&quot;&gt;Asahi Linux&lt;/a&gt;, &lt;a rel=&quot;nofollow&quot; href=&quot;https://docs.elementary.io/contributor-guide/development/generative-ai-policy&quot;&gt;elementaryOS&lt;/a&gt;, &lt;a rel=&quot;nofollow&quot; href=&quot;https://codeberg.org/forgejo/governance/src/commit/19ef60442456b92156a242ad1bbc1bcda98bef3b/AIAgreement.md#agreement&quot;&gt;Forgejo&lt;/a&gt;, &lt;a rel=&quot;nofollow&quot; href=&quot;https://gitlab.gnome.org/World/gedit/gedit/-/blob/master/docs/guidelines/no-llm-tools.md?ref_type=heads&quot;&gt;Gedit&lt;/a&gt;,  &lt;a rel=&quot;nofollow&quot; href=&quot;https://wiki.gentoo.org/wiki/Project:Council/AI_policy&quot;&gt;Gentoo&lt;/a&gt;, &lt;a rel=&quot;nofollow&quot; href=&quot;https://gitlab.gnome.org/GNOME/gimp/-/blob/master/.gitlab/merge_request_templates/default.md?plain=1#L11-12&quot;&gt;GIMP&lt;/a&gt;, &lt;a rel=&quot;nofollow&quot; href=&quot;https://codeberg.org/superseriousbusiness/gotosocial/src/branch/main/CODE_OF_CONDUCT.md#code-of-conduct&quot;&gt;GoToSocial&lt;/a&gt;, &lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/love2d/love/commit/147d39251c2618852c026f8cadf95f0ffd6a746f&quot;&gt;Löve2D&lt;/a&gt;, &lt;a rel=&quot;nofollow&quot; href=&quot;https://discourse.gnome.org/t/loupe-no-longer-allows-generative-ai-contributions/27327&quot;&gt;Loupe&lt;/a&gt;, &lt;a rel=&quot;nofollow&quot; href=&quot;https://www.netbsd.org/developers/commit-guidelines.html&quot;&gt;NetBSD&lt;/a&gt;, &lt;a rel=&quot;nofollow&quot; href=&quot;https://docs.postmarketos.org/policies-and-processes/development/contributing-and-ai.html&quot;&gt;postmarketOS&lt;/a&gt;, &lt;a rel=&quot;nofollow&quot; href=&quot;https://www.qemu.org/docs/master/devel/code-provenance.html#use-of-ai-generated-content&quot;&gt;Qemu&lt;/a&gt;, &lt;a rel=&quot;nofollow&quot; href=&quot;https://gitlab.redox-os.org/redox-os/redox/-/blob/master/CONTRIBUTING.md#ai-policy&quot;&gt;RedoxOS&lt;/a&gt;, &lt;a rel=&quot;nofollow&quot; href=&quot;https://book.servo.org/contributing/getting-started.html#ai-contributions&quot;&gt;Servo&lt;/a&gt;, &lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/nothings/stb/blob/master/CONTRIBUTING.md#ai-and-llm-are-forbidden&quot;&gt;stb libraries&lt;/a&gt;, &lt;a rel=&quot;nofollow&quot; href=&quot;https://ziglang.org/code-of-conduct/#strict-no-llm-no-ai-policy&quot;&gt;Zig&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;My deepest apologies if there already is such a policy, or if I'm asking in the wrong space.&lt;/p&gt;
</description>
<category>Meta</category>
<guid isPermaLink="true">https://ask.clojure.org/index.php/15004/clojure-contributions-policy-would-make-sense-clojure-adopt</guid>
<pubDate>Sun, 29 Mar 2026 13:14:25 +0000</pubDate>
</item>
<item>
<title>Is taggedliteral's equality check inefficient?</title>
<link>https://ask.clojure.org/index.php/15002/is-taggedliterals-equality-check-inefficient</link>
<description>&lt;p&gt;Following on from a very interesting article about tagged literals: &lt;a rel=&quot;nofollow&quot; href=&quot;https://buttondown.com/tensegritics-curiosities/archive/when-you-run-out-of-types/&quot;&gt;https://buttondown.com/tensegritics-curiosities/archive/when-you-run-out-of-types/&lt;/a&gt; I noticed that the implementing class checks for value equality before checking for tag equality.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;if (form != null ? !form.equals(that.form) : that.form != null) return false;
if (tag != null ? !tag.equals(that.tag) : that.tag != null) return false;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This leads to the following type of comparison that could be answered immediately but instead takes over a second:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;impl=&amp;gt; (time (= (tagged-literal 'foo (seq (range 1e7))) (tagged-literal 'bar (butlast (seq (range 1e7))))))
&quot;Elapsed time: 1911.677375 msecs&quot;
false
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;it checks if these huge seqs are equal and then compares the associated symbols. Swapping this seems identical semantically but with less computation.&lt;/p&gt;
</description>
<category>Records and Types</category>
<guid isPermaLink="true">https://ask.clojure.org/index.php/15002/is-taggedliterals-equality-check-inefficient</guid>
<pubDate>Fri, 27 Mar 2026 13:43:44 +0000</pubDate>
</item>
<item>
<title>Why doesn't defn also implicitly name the anonymous function it defines for recursion?</title>
<link>https://ask.clojure.org/index.php/15000/doesnt-defn-implicitly-anonymous-function-defines-recursion</link>
<description>&lt;p&gt;Why doesn't &lt;code&gt;defn&lt;/code&gt; implicitly name the function to create a named recursion point?&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(clojure.walk/macroexpand-all
  '(defn foo [x]
     (foo x)))
; =&amp;gt;
(def foo
  (fn*
    ([x]
     (foo x))))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This could instead expand to&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(def foo
  (fn* foo ; note the foo here
    ([x]
     (foo x))))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;How it works right now, &lt;code&gt;foo&lt;/code&gt; resolves to a global var &lt;code&gt;#'foo&lt;/code&gt;, which is created when the &lt;code&gt;(def ...)&lt;/code&gt; form is analyzed. In the second case, it resolves directly to the function object. Thus, it should save us a var dereference at runtime in this case.&lt;/p&gt;
&lt;p&gt;EDIT: Found out, this is exactly what &lt;a rel=&quot;nofollow&quot; href=&quot;https://clojure.org/reference/compilation#directlinking&quot;&gt;direct linking&lt;/a&gt; is used for.&lt;/p&gt;
</description>
<category>Macros</category>
<guid isPermaLink="true">https://ask.clojure.org/index.php/15000/doesnt-defn-implicitly-anonymous-function-defines-recursion</guid>
<pubDate>Sat, 21 Mar 2026 13:49:43 +0000</pubDate>
</item>
<item>
<title>Controlled Bailout, Jira issue 2213</title>
<link>https://ask.clojure.org/index.php/14999/controlled-bailout-jira-issue-2213</link>
<description>&lt;p&gt;I would like to improve &lt;a rel=&quot;nofollow&quot; href=&quot;https://clojure.atlassian.net/browse/CLJ-2213&quot;&gt;Issue 2213&lt;/a&gt; as follows. Do you think, this makes sense? Shall I become contributor for this? &lt;/p&gt;
&lt;p&gt;The new description would be:&lt;/p&gt;
&lt;p&gt;When developing Input-Process-Output tools I am often in the situation, that I have a sequence of activities (e.g. opening a file, spec checking a file, calling external tools, creating files), which each could fail in certain ways. Clojure does not have a good way to control such a sequence of activities in a way that all sorts of things, which could go wrong, can be handled comfortably. In imperative programming languages concepts like early exit or bailout are used. These are not not very functional. Unfortunately practical problems are often like this.&lt;/p&gt;
&lt;p&gt;The issue is a bit more general and a solution would be nice not only for those who develop such sort of tools. So I can give a simple example.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(let [config-file (get-file-from-network xy)
      config-file (parse-edn config-file)
      syntax-ok?   (spec-check config-file)]
  (do-something-with config-file))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As all these steps can fail, we could instead implement it like this.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(if-let [config-file (get-file-from-network xy)]
  (if-let [config-file (parse-edn config-file)]
    (if (spec-check config-file)
      (do-something-with config-file))))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now the code has suffered already a lot. The sequential nature of the problem is lost. And it is not even doing what we need. We have to report to the user what went wrong.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(if-let [config-file (get-file-from-network xy)]
  (if-let [config-file (parse-edn config-file)]
    (if (spec-check config-file)
      (do-something-with config-file)
      :file-has-syntax-errors)
    :file-not-valid-edn)
  :file-cannot be openned)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But this is still not doing what we need. We have to provide more information about each failure. If a file cannot be openned, is it because the file does not exist or we do not have read permissions? And what did the spec check tell us? So we cannot just use &lt;code&gt;nil&lt;/code&gt; as a universal failure. We must deliver more information when failing. And we cannot use if-let, either. So we are not even done.&lt;/p&gt;
&lt;p&gt;This problem report asks for a better solution for this conceptual challenge.&lt;/p&gt;
&lt;p&gt;This example depicts a conflict that should not happen when using an appropriate programming language: First we are able to quickly make a prototype. But in the end the final code has not much in common with the first code any more. The final design is not driven by the problem domain, but by the technical need for an error handling. The need for a bailout mechanism in this example imposes too many huge code changes.&lt;/p&gt;
&lt;p&gt;The principal problem with all these solutions is that they coerce a sequence of actions into something which is not a sequence. If your problem is a sequence, then the implementation should also be a sequence.&lt;/p&gt;
&lt;h2&gt;Idea: Exceptions&lt;/h2&gt;
&lt;p&gt;As an alternative implementation I went with Exceptions. But it feels wrong, because I am talking about things, that are expected to fail. I cannot just use the Exceptions that are comming out of Java for example when opening a file for read. I need detailed information, what went wrong. If you are a command line tool, it is expected from you, that you provide good error messages. I ended up catching and rethrowing exceptions everywhere in the program.&lt;/p&gt;
&lt;h2&gt;Idea: Like for/doseq&lt;/h2&gt;
&lt;p&gt;For me I created a small macro, that extends &lt;code&gt;let&lt;/code&gt;. Then I use this syntax:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(let [[config-file error] (get-file-from-network xy)
      :escape     error
      config-file (parse-edn config-file)
      syntax-ok?   (spec-check config-file)]
  (do-something-with config-file))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This often allows a surprisingly intuitive code. For example here:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(let [[config-file error-code] (get-file-from-network xy)
      :escape     (if (= error-code :does-not-exist) 
                    :file-xy-does-not-exist)
      :escape     (if (= error-code :io-error)
                    :file-xy-cannot-be-read)
      [config-file error-code] (parse-edn config-file)
      :escape     (if error-code :file-xy-not-legal-edn)
      syntax-ok?   (spec-check config-file)]
  (do-something-with config-file))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is inspired by the &lt;code&gt;for&lt;/code&gt;/&lt;code&gt;doseq&lt;/code&gt;. But I don't claim that this is a good solution for Clojure (although I think so). But I think, the &lt;code&gt;let&lt;/code&gt; macro is a good candidate when improving how Clojure can be used for such imperative things.&lt;/p&gt;
&lt;h2&gt;Idea: Using &lt;code&gt;if-let&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;I also investigated the solution, that was originally proposed by this issue.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(if-let [config-file (get-file-from-network xy)
         config-file (parse-edn config-file)
         config-file-ok? (spec-check config-file)]
  (do-something-with config-file)
  :error)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This problem with this solution is that none of the bindings are available in the else part. That makes it very hard to react accordingly. This is a nice and small new language feature. But I don't think, that in practice it would be of help so often. The example from the original issue was very artificial with mathematical operations that cannot fail. The first draft of this issue with that artificial example does not actally describe a real problem. That is why this issue has completelly been rewritten.&lt;/p&gt;
&lt;p&gt;Or course we could still bind everything, which was not failed. But I don't think, we would want that. It would have very interesting consequences to the compiling model.&lt;/p&gt;
&lt;h2&gt;Idea: Threading macros&lt;/h2&gt;
&lt;p&gt;As this issue is a about a sequence of activities, a new type of threading macro (e.g. &lt;code&gt;let-&amp;gt;&lt;/code&gt;) could also be an intuitive solution. But I have not tried anything like this.&lt;/p&gt;
&lt;h2&gt;Final Words&lt;/h2&gt;
&lt;p&gt;The principle challenge is, that all these solutions establish a sort of alternative control flow. It is a hard challenge to do this right, especially in a functional language. Like exceptions, that immediatelly exit and magically jump somewhere else. Clojure as a practically language could address this challenge.&lt;/p&gt;
</description>
<category>Clojure</category>
<guid isPermaLink="true">https://ask.clojure.org/index.php/14999/controlled-bailout-jira-issue-2213</guid>
<pubDate>Sat, 21 Mar 2026 10:14:48 +0000</pubDate>
</item>
<item>
<title>Is the recent change to flow's futurize safe?</title>
<link>https://ask.clojure.org/index.php/14994/is-the-recent-change-to-flows-futurize-safe</link>
<description>&lt;p&gt;Previously flow's futurize would rethrow any exceptions thrown by the function when deref'ed. With the recent changes to return a CompletableFuture it no longer does that and instead if the function throws deref'ing will just hang forever.&lt;/p&gt;
</description>
<category>core.async</category>
<guid isPermaLink="true">https://ask.clojure.org/index.php/14994/is-the-recent-change-to-flows-futurize-safe</guid>
<pubDate>Tue, 17 Mar 2026 15:54:00 +0000</pubDate>
</item>
<item>
<title>Evaluating forms using eval can create a valid undesirable recursion point</title>
<link>https://ask.clojure.org/index.php/14991/evaluating-forms-using-create-valid-undesirable-recursion</link>
<description>&lt;p&gt;When the &lt;code&gt;eval&lt;/code&gt; function in Clojure is called with an argument that is an instance of &lt;code&gt;IPersistentCollection&lt;/code&gt; which likely isn't a special def-like form (the first element isn't a symbol at all or it does not start with &lt;code&gt;&quot;def&quot;&lt;/code&gt;), the form is first wrapped in an anonymous function which then gets compiled and invoked, which indirectly evaluates the original form.&lt;/p&gt;
&lt;p&gt;There aren't any extra checks performed and it makes forms like these 2 valid, which should normally be rejected and a compiler exception should be thrown:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(recur)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;or&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(let []
  (print &quot;Hello&quot;)
  (Thread/sleep 1000)
  (recur))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;where the 2nd form keeps printing &quot;Hello&quot; and loops infinitely over the outer wrapper function.&lt;/p&gt;
</description>
<category>Clojure</category>
<guid isPermaLink="true">https://ask.clojure.org/index.php/14991/evaluating-forms-using-create-valid-undesirable-recursion</guid>
<pubDate>Mon, 16 Mar 2026 23:17:54 +0000</pubDate>
</item>
<item>
<title>Optimized str function</title>
<link>https://ask.clojure.org/index.php/14990/optimized-str-function</link>
<description>&lt;p&gt;Opimized version of str function:    &lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(defn my-str
  (^String [] &quot;&quot;)
  (^String [^Object x]
   (if (nil? x) &quot;&quot; (. x (toString))))
  (^String [^Object x &amp;amp; ys]
   (let [sb (StringBuilder. (if (nil? x) &quot;&quot; (. x (toString))))]
     (loop [ys (seq ys)]
       (if-not (nil? ys)
         (let [x (.first ys)]
           (if-not (nil? x)
             (.append sb (.toString ^Object x)))
           (recur (.next ys)))))
     (.toString sb))))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Benchmarks:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(let [xs (vec (range 1000))]
    (criterium/bench
      (apply my-str xs)))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Evaluation count : 2577840 in 60 samples of 42964 calls.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;         Execution time mean : 23.611394 µs

(let [xs (vec (range 1000))]
    (criterium/bench
      (apply str xs)))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Evaluation count : 1375200 in 60 samples of 22920 calls.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;         Execution time mean : 42.015320 µs
&lt;/code&gt;&lt;/pre&gt;
</description>
<category>Sequences</category>
<guid isPermaLink="true">https://ask.clojure.org/index.php/14990/optimized-str-function</guid>
<pubDate>Mon, 16 Mar 2026 11:12:53 +0000</pubDate>
</item>
</channel>
</rss>