Has anyone written sci cljs bindings for core.match? I’m looking to add them to a forked nbb. I tried emulating the https://github.com/babashka/babashka/blob/master/feature-core-match/babashka/impl/match.clj with https://github.com/logseq/nbb-logseq/blob/add-core-match-failing/features/core.match/src/nbb/impl/core_match.cljs. However this failed with Unable to resolve var match/match. I thought I’d read somewhere that copy-var works for macros. In the meantime, I have a hacky approach I’ll expand on in a thread
Gotcha. The https://github.com/clojure/core.match/blob/753e8a30de9c487ceba8ff7d39435bf87edff505/src/main/clojure/cljs/core/match.clj#L19-L32 macro is dependent on a clojure var, https://github.com/clojure/core.match/blob/753e8a30de9c487ceba8ff7d39435bf87edff505/src/main/clojure/clojure/core/match.clj#L2083-L2096 ,which is at the bottom of a 2k line jvm ns. The fork is basically doing the work of converting that jvm ns to be cljs compatible. I’ll give the fork a try
I ran tests on viebel’s fork. Good news is that most match tests. Bad news is that ones involving a map fail hard because cljs.core/ILookup doesn’t exist. If you’re curious, you can checkout https://github.com/logseq/nbb-logseq/tree/add-core-match and just run bb test as the nbb compiled assets are included. I looked at modifying the ILookup calls in the fork but there are about https://github.com/viebel/abbinare/blob/master/src/main/clojure/cljs/core/match.cljc . Going down this path seems brittle and error prone. Unless I’m missing something, I’ll look at ripping out core.match for the code I’m making nbb compatible. I can add this use case to https://github.com/babashka/sci/issues/639 if it seems helpful
this is only applicable if you are trying to run core.match from source? your original post was about SCI CLJS bindings (meaning configuration) which is a different use case?
Not sure I follow. I’m building nbb-logseq with https://github.com/logseq/nbb-logseq/blob/add-core-match/features/core.match/src/nbb/impl/core_match.cljs . When I run https://github.com/logseq/nbb-logseq/blob/add-core-match/test/core_match_match_test.cljs with nbb-logseq (via bb test), nbb fails hard with Could not resolve symbol: cljs.core/ILookup
is this because a macro expands into that symbol?
Possibly. The full failure looks like:
Running core.match tests...
----- Error --------------------------------------
Message: Could not resolve symbol: cljs.core/ILookup
Location: /Users/me/code/work/nbb-logseq/test/core_match_match_test.cljs:110:11
Phase: analysis
----- Context ------------------------------------
106: (deftest test-map-patterns
107: (testing "Map patterns"
108: (is
109: (= (let [x {:a 1 :b 1}]
110: (match [x]
^--- Could not resolve symbol: cljs.core/ILookup
111: [{:a _ :b 2}] :a0
112: [{:a 1 :b 1}] :a1
113: [{:c 3 :d _ :e 4}] :a2
114: :else nil))
115: :a1))
The sci bindings compile https://github.com/viebel/abbinare/blob/master/src/main/clojure/cljs/core/match.cljc which has about a dozen references to cljs.core/ILookupThis looks like it's used in a macro expansion: https://github.com/viebel/abbinare/blob/e1e4a3c9d083b495a02c080f86a05aa10275e6d0/src/main/clojure/cljs/core/match.cljc#L149
you can at least add ILookup to nbb.core's core config to get past this
probably still won't work but let's see what the next step is
Added ILookup to nbb.core and pushed to https://github.com/logseq/nbb-logseq/tree/add-core-match. Tests can now run with bb test but understandably 20 of 91 assertions now fail
failing how? more info would be helpful
Sure. It seems tests are failing since maps aren’t matching like they should. Here’s the full test output:
$ bb test
Running cljs-time tests...
Testing cljs-time-format-test
Ran 1 tests containing 19 assertions.
0 failures, 0 errors.
Running core.match tests...
benchmarking
basic Maranget example hand written
2866665
"Elapsed time: 518.914458 msecs"
basic Maranget example
"Elapsed time: 2768.185958 msecs"
Testing core-match-match-test
FAIL in (test-map-patterns) (/Users/me/code/work/nbb-logseq/test/core_match_test_runner.cljs:109)
Map patterns
expected: (= (let [x {:a 1, :b 1}] (match [x] [{:a _, :b 2}] :a0 [{:a 1, :b 1}] :a1 [{:c 3, :d _, :e 4}] :a2 :else nil)) :a1)
actual: (not (= nil :a1))
FAIL in (test-map-patterns) (/Users/me/code/work/nbb-logseq/test/core_match_test_runner.cljs:117)
Map patterns
expected: (= (let [x {:a 1, :b 2}] (match [x] [{:a _, :b 2}] :a0 [{:a 1, :b 1}] :a1 [{:c 3, :d _, :e 4}] :a2 :else nil)) :a0)
actual: (not (= nil :a0))
FAIL in (test-map-patterns) (/Users/me/code/work/nbb-logseq/test/core_match_test_runner.cljs:125)
Map patterns
expected: (= (let [x {:c 3, :d 9, :e 4}] (match [x] [{:a _, :b 2}] :a0 [{:a 1, :b 1}] :a1 [{:c 3, :d _, :e 4}] :a2 :else nil)) :a2)
actual: (not (= nil :a2))
FAIL in (test-map-patterns) (/Users/me/code/work/nbb-logseq/test/core_match_test_runner.cljs:141)
Map patterns
expected: (= (let [x {:a 1, :b 1}] (match [x] [{:a _, :b 1}] :a0 [{:a 1, :b _}] :a1 [{:c 3, :d _, :e 4}] :a2 :else [])) :a0)
actual: (not (= [] :a0))
FAIL in (test-map-patterns) (/Users/me/code/work/nbb-logseq/test/core_match_test_runner.cljs:149)
Map patterns
expected: (= (let [x {:a 1, :b 1, :c 1}] (match [x] [{:a _, :b 2}] :a0 [{:a 1, :b _}] :a1 [{:c 3, :d _, :e 4}] :a2 :else [])) :a1)
actual: (not (= [] :a1))
FAIL in (test-map-patterns) (/Users/me/code/work/nbb-logseq/test/core_match_test_runner.cljs:157)
Map patterns
expected: (= (let [x {:a 1, :b 1}] (match [x] [{:a _, :b 2}] :a0 [{:a _, :b _}] :a1 [{:c 3, :d _, :e 4}] :a2 :else [])) :a1)
actual: (not (= [] :a1))
FAIL in (test-map-patterns) (/Users/me/code/work/nbb-logseq/test/core_match_test_runner.cljs:173)
Map patterns
expected: (= (let [x {:a 1, :b 1}] (match [x] [{:b 1}] :a0 [{:a _, :b _}] :a1 [{:a _, :b _}] :a2 :else [])) :a0)
actual: (not (= [] :a0))
FAIL in (test-map-patterns) (/Users/me/code/work/nbb-logseq/test/core_match_test_runner.cljs:181)
Map patterns
expected: (= (let [x {:a 1, :b 1}] (match [x] [{}] :a0 [{:a _, :b _}] :a1 [{:a 1, :b 1}] :a2 :else [])) :a0)
actual: (not (= [] :a0))
FAIL in (test-map-patterns) (/Users/me/code/work/nbb-logseq/test/core_match_test_runner.cljs:189)
Map patterns
expected: (= (let [x {:a 1, :b 1}] (match [x] [{:x nil, :y nil}] :a0 [{:a _, :b _}] :a1 [{:a 1, :b 1}] :a2 :else [])) :a1)
actual: (not (= [] :a1))
FAIL in (test-map-patterns) (/Users/me/code/work/nbb-logseq/test/core_match_test_runner.cljs:197)
Map patterns
expected: (= (let [x {:a 1, :b 2}] (match [x] [({:a _, :b 2} :only [:a :b])] :a0 [{:a 1, :c _}] :a1 [{:c 3, :d _, :e 4}] :a2 :else [])) :a0)
actual: (not (= [] :a0))
FAIL in (test-map-patterns) (/Users/me/code/work/nbb-logseq/test/core_match_test_runner.cljs:205)
Map patterns
expected: (= (let [x {:a 1, :b 2, :c 3}] (match [x] [({:a _, :b 2} :only [:a :b])] :a0 [{:a 1, :c _}] :a1 [{:c 3, :d _, :e 4}] :a2 :else [])) :a1)
actual: (not (= [] :a1))
FAIL in (test-map-patterns) (/Users/me/code/work/nbb-logseq/test/core_match_test_runner.cljs:213)
Map patterns
expected: (= (let [x {:a 1, :b 2}] (match [x] [{:a a, :b b}] [:a0 a b] :else [])) [:a0 1 2])
actual: (not (= [] [:a0 1 2]))
FAIL in (test-or-patterns) (/Users/me/code/work/nbb-logseq/test/core_match_test_runner.cljs:269)
Or patterns
expected: (= (let [x {:a 3} y nil z nil] (match [x y z] [{:a (:or 1 2)} _ _] :a0 [{:a (:or 3 4)} _ _] :a1 :else [])) :a1)
actual: (not (= [] :a1))
FAIL in (test-else) (/Users/me/code/work/nbb-logseq/test/core_match_test_runner.cljs:357)
Test :else support
expected: (= (let [v {:a 1}] (match [v] [{:a a}] 1 :else 21)) 1)
actual: (not (= 21 1))
FAIL in (test-edge-cases-4) (/Users/me/code/work/nbb-logseq/test/core_match_test_runner.cljs:556)
Edge cases 4
expected: (= (let [x {:a 1, :b 2, :c 10, :d 30}] (match [x] [({:a _, :b _, :c _, :d _} :only [:a :b :c :d])] :a-1 [({:a _, :b 2} :only [:a :b])] :a0 [{:a 1, :c _}] :a1 [{:c 3, :d _, :e 4}] :a2 :else [])) :a-1)
actual: (not (= [] :a-1))
FAIL in (test-edge-cases-4) (/Users/me/code/work/nbb-logseq/test/core_match_test_runner.cljs:567)
Edge cases 4
expected: (and (= (let [m {:a 1}] (match [m] [({:a 1} :only [:a])] :a0 :else :a1)) :a0) (= (let [m {:a 1, :b 2}] (match [m] [({:a 1} :only [:a])] :a0 :else :a1)) :a1))
actual: false
FAIL in (test-edge-cases-4) (/Users/me/code/work/nbb-logseq/test/core_match_test_runner.cljs:580)
Edge cases 4
expected: (= (let [m {:foo 1, "bar" 2}] (match [m] [{:foo 1, "bar" 2}] :a0 :else :a1)) :a0)
actual: (not (= :a1 :a0))
FAIL in (test-app-patterns) (/Users/me/code/work/nbb-logseq/test/core_match_test_runner.cljs:902)
Function application patterns
expected: (= (match [m] [{:a (2 :<< inc), :b _}] :match1 [{:a (3 :<< inc), :b _}] :match2 :else :no-match) :match2)
actual: (not (= :no-match :match2))
FAIL in (test-misc-tickets) (/Users/me/code/work/nbb-logseq/test/core_match_test_runner.cljs:918)
Misc. tickets
expected: (= (let [xqq {:cz 1, :dz 2}] (match [xqq] [{:z a, :zz b}] [:a0 a b] [{:cz a, :dz b}] [:a2 a b] :else [])) [:a2 1 2])
actual: (not (= [] [:a2 1 2]))
FAIL in (test-misc-tickets) (/Users/me/code/work/nbb-logseq/test/core_match_test_runner.cljs:926)
Misc. tickets
expected: (= (let [xmm {:bz 2}] (match [xmm] [{:az a}] [:a0 a] [{:bz b}] [:a1 b] :else [])) [:a1 2])
actual: (not (= [] [:a1 2]))
Ran 20 tests containing 91 assertions.
20 failures, 0 errors.This is because (instance? ILookup {}) is failing in nbb.
oh no sorry about that, instance? isn't being used in cljs branch
I suspect this one fails:
(satisfies? ILookup ~ocr)are you running with a fork of this library?
if so, you can try to add a function that checks the satisfies condition like this:
'satisfies-ILookup? #(satifies? ILookup %)
to the namespace config and then substitute that insteadthen I bet some tests will start working!
I’m not running a fork of abbinare yet. I can try tomorrow. After I add that fn I can add a :org.babashka/nbb conditional to https://github.com/viebel/abbinare/blob/e1e4a3c9d083b495a02c080f86a05aa10275e6d0/src/main/clojure/cljs/core/match.cljc#L1277 . I’d be happily surprised if that’s the only ILookup call I have to change 🤞
I think you're confusing things. That source code won't be seen by nbb if you add it via SCI bindings
but you can however make this function as part of that lib and then it will work there as well
so just something like
(defn satisfies-ILookup? [x] (satisfies? ILookup x))
and then use this function in the macro-expansion I pointed atyou then have to change nothing about the SCI bindings I think
oh yes, you do need to add that function to the SCI bindings as well of course since it's used in the macro-expansion
anyway, in that case the lib will still work with SCI bindings and in regular CLJS
thumbsup_all🤞
Tests all pass! Thanks for the guidance. https://github.com/logseq-cldwalker/abbinare/commit/1d435ea6b3c6269196c6f1b137af78790a8b767c is the abbinare change. https://github.com/logseq/nbb-logseq/tree/add-core-match adds the core.match bindings. One weird quick is that when I pulled in the latest nbb with the updated sci, building nbb-logseq fails with
Error building classpath. Unable to compare versions for org.babashka/sci: {:mvn/version "0.10.46", :deps/manifest :mvn} and {:git/url "", :git/sha "56104c81cb7a3804f8ee84aa64b313dc7143f30e", :deps/manifest :deps, :deps/root "/Users/me/.gitlibs/libs/org.babashka/sci/56104c81cb7a3804f8ee84aa64b313dc7143f30e"}
I wasn’t seeing this before when I depended on https://github.com/babashka/nbb/blob/9119dbe9b5f660cb77d29058b3b762978ee4b939/deps.edn which also depended on a git-based sci. Anyways, I’ll figure it out and look forward to using core.match in nbb next weeknice, congrats!
With chat-gpt’s help I was able to get https://github.com/logseq/nbb-logseq/blob/add-core-match/features/core.match/src/nbb/impl/core_match.cljs but it requires https://github.com/viebel/abbinare. Gonna have to poke at it more to see if it fully works
@borkdude I saw you gave some advice on these bindings in https://clojurians.slack.com/archives/C03DPCLCV9N/p1679434303385649?thread_ts=1679424994.838549&cid=C03DPCLCV9N . Is the above approach what you had in mind?
it's just a matter of fixing the macro expansion to use fully qualified vars I think?
I don't know if you have to fork core.match, but you need to copy the macros from clj to cljs
since those are normally executed in JVM Clojure
but perhaps that's just what viebel's version does, dunno