<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0">
<channel>
<title>Clojure Q&amp;A - Questions without answers in ClojureCLR</title>
<link>https://ask.clojure.org/index.php/unanswered/clojureclr</link>
<description></description>
<item>
<title>Threading macro with update and when produces incorrect results</title>
<link>https://ask.clojure.org/index.php/14788/threading-macro-with-update-when-produces-incorrect-results</link>
<description>&lt;p&gt;Environment:&lt;br&gt;
- ClojureCLR version: 1.12.2&lt;br&gt;
- .NET version: 10&lt;br&gt;
- OS: MacOS 26.1&lt;/p&gt;
&lt;p&gt;Description:&lt;br&gt;
The pattern &lt;code&gt;(-&amp;gt; map (update :key #(when % (fn %))))&lt;/code&gt; &lt;br&gt;
fails in ClojureCLR but works correctly in Clojure JVM. When chaining multiple updates in a threading macro where the anonymous function contains &lt;code&gt;when&lt;/code&gt;, the result is incorrect or causes runtime errors.&lt;/p&gt;
&lt;p&gt;Expected Behavior:&lt;br&gt;
Should work identically to Clojure JVM - &lt;code&gt;update&lt;/code&gt; with a function that&lt;br&gt;
returns &lt;code&gt;nil&lt;/code&gt; should associate &lt;code&gt;nil&lt;/code&gt; to the key.&lt;br&gt;
Actual Behavior:&lt;br&gt;
[Crashes/Wrong values/500 errors in web handlers]&lt;br&gt;
Workaround:&lt;br&gt;
Use explicit conditionals instead:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt; (let [value (when (:key map) (fn (:key map)))]
    (if value (assoc map :key value) map))'
&lt;/code&gt;&lt;/pre&gt;
</description>
<category>ClojureCLR</category>
<guid isPermaLink="true">https://ask.clojure.org/index.php/14788/threading-macro-with-update-when-produces-incorrect-results</guid>
<pubDate>Sat, 29 Nov 2025 07:16:52 +0000</pubDate>
</item>
<item>
<title>Porting clojure libraries w/ java interop to clojure-clr</title>
<link>https://ask.clojure.org/index.php/14684/porting-clojure-libraries-w-java-interop-to-clojure-clr</link>
<description>&lt;p&gt;I've been browsing around to understand the ecosystem.&lt;/p&gt;
&lt;p&gt;I see some libraries are ported to use CLR interop, like core.logic, some are part way finished, like core.async.&lt;/p&gt;
&lt;p&gt;Here is one maintainer's concerns, they would much like to point CLR users at a fork with CLR interop maintained by someone else:&lt;br&gt;
&lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/weavejester/medley/pull/96&quot;&gt;https://github.com/weavejester/medley/pull/96&lt;/a&gt;&lt;br&gt;
&lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/weavejester/medley/pull/65&quot;&gt;https://github.com/weavejester/medley/pull/65&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;For fun I examined how to use formal logic to do the code translation. Using Spec, and core.logic for code generation perhaps. I think it would require a lot of knowledge representation.&lt;/p&gt;
&lt;p&gt;It might be easier, for these non-core/crucial libraries to use LLMs to do the code translation, and direct the outputs into a set of forks. Perhaps the core libraries used as training data on what to do. This author has some great insights and details on a plausible workflow(s) including with the utility of editor integration. He has done interop translation and work with clojure:&lt;br&gt;
&lt;a rel=&quot;nofollow&quot; href=&quot;https://m.youtube.com/watch?v=oNhqqiKuUmw&quot;&gt;https://m.youtube.com/watch?v=oNhqqiKuUmw&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;As it is only the interop which requires translation (subsets of clojure files), with a skilled hand there might be better results than some of what he illustrates.&lt;/p&gt;
&lt;p&gt;I looked around for a spec for the dotnet core API. I saw one they used to maintain but couldn't find a recent one. Though, all this LLM stuff is beyond me at this time. I thought to share some of my exploration.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;EDIT:&lt;/strong&gt; Found the dotnet API spec/reference for netstandard 2.1.0, I think someone wrote they since moved it into dotnet/runtime but I couldn't find it there, dunno if this helps: &lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/dotnet/standard/blob/v2.1.0/src/netstandard/ref/System.IO.cs&quot;&gt;https://github.com/dotnet/standard/blob/v2.1.0/src/netstandard/ref/System.IO.cs&lt;/a&gt;&lt;/p&gt;
</description>
<category>ClojureCLR</category>
<guid isPermaLink="true">https://ask.clojure.org/index.php/14684/porting-clojure-libraries-w-java-interop-to-clojure-clr</guid>
<pubDate>Fri, 15 Aug 2025 01:31:53 +0000</pubDate>
</item>
<item>
<title>Does clojure-clr work on Android?</title>
<link>https://ask.clojure.org/index.php/14512/does-clojure-clr-work-on-android</link>
<description>&lt;p&gt;&lt;strong&gt;EDIT: &lt;/strong&gt; Answer is YES. Below is my long-winded exploration.&lt;/p&gt;
&lt;p&gt;I see one of the reasons for clojure-clr-next is it will work on more platforms, is Android one of those?&lt;/p&gt;
&lt;p&gt;I'm using Termux to operate dotnet on Android.&lt;/p&gt;
&lt;p&gt;Both the clojure-clr global dotnet tool and locally compiled clojure-clr fail with exit code 1, no exceptions or anything. I tried dotnet-trace and it gets a partial trace, but no minidump. Puzzling as with the partial trace, the  documentation indicates an expectation of a minidump, maybe there is some unmet condition to emit the minidump I'm not aware of yet (env variables for it didn't work).&lt;/p&gt;
&lt;p&gt;In the trace here is an early line followed by some of the last lines:&lt;br&gt;
&lt;code&gt;`&lt;/code&gt;&lt;br&gt;
&quot;system.linq!System.Linq.Enumerable.SelectManyS\ingleSelectorIterator\u003cSystem.Reflection.As\sembly,System.Type\u003e.MoveNext()&quot;&lt;/p&gt;
&lt;p&gt;[...]&lt;br&gt;
&quot;system.collections!System.Collections.Generic.\&lt;br&gt;
SortedSet\u003cSystem.Collections.Generic.KeyVa\luePair\u003cSystem.Int32,clojure.lang.CljCompi\ler.Ast.FnMethod\u003e\u003e.AddIfNotPresent(Sy\stem.Collections.Generic.KeyValuePair`2\u003cin\t,&lt;/p&gt;
&lt;p&gt;[...last line...]&lt;br&gt;
&quot;ManagedModule!System.Buffers.SharedArrayPool\u\003cSystem.Byte\u003e.Trim()&quot;&lt;br&gt;
&lt;code&gt;`&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;So maybe something to do with reflection, or that SharedArrayPool?&lt;/p&gt;
&lt;p&gt;I tried inserting some logging to Clojure.Main, but nothing logged as it appears to fail before CljMain.Main() is called. Possibly fails during setting up attributes on one of the classes, in one of the Symbol.intern() or RT.var() calls or somewhere else?&lt;/p&gt;
&lt;p&gt;Couldn't run the &lt;code&gt;dotnet msbuild build.proj -t:Test -p:TestTargetFramework=net8.0&lt;/code&gt;, fails with:&lt;br&gt;
&lt;code&gt;Clojure.Main -&amp;gt; /data/data/com.termux/files/home/dev/clojure-clr/Clojure/Clojure.Main/bin/Debug/net8.0/Clojure.Main.dll
  ClojureCompileAssets = ''
  ClojureMainAssets = ''
  ClojureTestsAssets = ''
/data/data/com.termux/files/home/dev/clojure-clr/Clojure/build.proj(177,5): error MSB3073: The command &quot;dotnet run --project /data/data/com.termux/files/home/dev/clojure-clr/Clojure/Clojure.Main --framework net8.0 -c Debug -p:TargetOS=linux-bionic -p:TargetPlatform=arm64 -p:TargetFramework=net8.0 -p:TargetFrameworks='net8.0' -- run_test.clj&quot; exited with code 1.&lt;/code&gt;&lt;br&gt;
I had to edit build.proj a bit to get custom -p:TargetFrameworks and such to pass through, but still fails with exit code 1.&lt;/p&gt;
&lt;p&gt;Well I'll continue poking around in this uncharted territory.&lt;/p&gt;
</description>
<category>ClojureCLR</category>
<guid isPermaLink="true">https://ask.clojure.org/index.php/14512/does-clojure-clr-work-on-android</guid>
<pubDate>Sat, 19 Apr 2025 19:59:28 +0000</pubDate>
</item>
<item>
<title>CLR behavior of tools.namespace does not match the JVM implementation</title>
<link>https://ask.clojure.org/index.php/14284/clr-behavior-tools-namespace-does-not-match-implementation</link>
<description>&lt;p&gt;I noticed a few behavioral differences between the CLR and JVM implementations of &lt;code&gt;tools.namespace&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;As an example, the following tests will pass in the JVM implementation and fail in the CLR implementation. In CLR, &lt;code&gt;files-2&lt;/code&gt; is empty and &lt;code&gt;::dir/time&lt;/code&gt; is an instant.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(ns clojure.tools.namespace.repl-test
  (:require [clojure.test :refer [deftest is]]
            [clojure.tools.namespace.dir :as dir]
            [clojure.tools.namespace.find :as find]
            [clojure.tools.namespace.repl :as repl]
            [clojure.tools.namespace.test-helpers :as help]))

(deftest t-repl-scan
  (let [dir        (help/create-temp-dir &quot;t-repl-scan&quot;)
        _main-clj  (help/create-source dir 'example.main :clj '[example.one])
        _one-cljc  (help/create-source dir 'example.one :clj)
        _other-dir (help/create-temp-dir &quot;t-repl-scan-other&quot;)
        files-1    (::dir/files (repl/scan {:platform find/clj}))
        files-2    (::dir/files (repl/scan {:platform find/clj}))]
    (is (not-empty files-1))
    (is (not-empty files-2))
    (is (= files-1 files-2))))

(deftest t-repl-scan-time
  (let [scan (repl/scan {:platform find/clj})]
    (is (integer? (::dir/time scan)))))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;After discussing with other contributors, the question of intent came up and this test was proposed as something that correctly captures the intent of &lt;code&gt;repl/scan&lt;/code&gt;. However, if this is the intended behavior, then a new problem arises as this test fails in the JVM implementation.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(deftest t-repl-scan
  (try
    (let [dir       (help/create-temp-dir &quot;t-repl-scan&quot;)
          _main-clj (help/create-source dir 'example.main :clj '[example.one])
          _one-cljc (help/create-source dir 'example.one :clj)
          other-dir (help/create-temp-dir &quot;t-repl-scan-other&quot;)
          _         (repl/set-refresh-dirs dir other-dir)
          scan1     (repl/scan {:platform find/clj})
          scan2     (repl/scan {:platform find/clj})
          files-1   (::dir/files scan1)
          files-2   (::dir/files scan2)]
      (is (= (count files-1) 2))
      (is (= (count files-2) 0)))
    (finally (repl/clear))))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A couple things I think would help here:&lt;br&gt;
 1. Flesh out the &lt;code&gt;tools.namespace&lt;/code&gt; (JVM) test suite to capture all the intended behavior.&lt;br&gt;
 2. Realign &lt;code&gt;clr.tools.namespace&lt;/code&gt; with &lt;code&gt;tools.namespace&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Point 1 will provide a good baseline for point 2, as well as any other existing/future ports of &lt;code&gt;tools.namespace&lt;/code&gt; and help prevent things from diverging in the future as changes are made.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;As of writing, &lt;code&gt;repl/scan&lt;/code&gt; will throw an &lt;code&gt;InvalidCastException&lt;/code&gt; on CLR. To fix this, replace &lt;code&gt;clojure.tools.namespace.dir/modified-files&lt;/code&gt; with this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(defn- modified-files [tracker files]
  (filter #(DateTime/op_LessThan ^DateTime (::time tracker System.DateTime/UnixEpoch) (.get_LastWriteTimeUtc ^FileSystemInfo %)) files))
&lt;/code&gt;&lt;/pre&gt;
</description>
<category>ClojureCLR</category>
<guid isPermaLink="true">https://ask.clojure.org/index.php/14284/clr-behavior-tools-namespace-does-not-match-implementation</guid>
<pubDate>Thu, 05 Dec 2024 14:44:05 +0000</pubDate>
</item>
</channel>
</rss>