sci

jyn 2025-08-17T02:08:47.247349Z

update-keys doesn't seem to be bound in an SCI context? i checked that it's bound to clojure.core/update-keys in a host repl, i'm not sure why SCI is different.

jyn 2025-08-17T02:11:45.318939Z

oh gosh i didn't realize that the default namespace is created by listing out all variables that are copied https://github.com/babashka/sci/blob/56104c81cb7a3804f8ee84aa64b313dc7143f30e/src/sci/impl/namespaces.cljc#L1652

jyn 2025-08-17T02:11:57.793969Z

i suspect update-keys is an oversight? i can make a PR if you're interested

jyn 2025-08-17T02:19:10.685259Z

if it helps, here's a list of all the things that are bound in clojure.core but not sci's clojure.core:

user=> (clojure.set/difference (set (keys (ns-publics 'clojure.core))) (set (keys sci.impl.namespaces/clojure-core)))
#{primitives-classnames restart-agent ensure proxy-mappings ref-min-history gen-class println-str slurp import splitv-at pvalues bases read+string dosync stream-transduce! send-via random-uuid PrintWriter-on future-call resultset-seq struct *source-path* with-loading-context NaN? compile set-error-mode! set-agent-send-executor! remove-tap gen-interface *command-line-args* -cache-protocol-fn await spit future-done? -reset-methods partitionv load stream-into! *verbose-defrecords* stream-reduce! pmap error-mode StackTraceElement->vec alter with-precision shutdown-agents *use-context-classloader* await1 ref-set defstruct update-vals definline find-protocol-impl method-sig unquote-splicing future definterface add-tap pcalls *allow-unresolved-vars* vector-of set-error-handler! inst-ms* default-data-readers ->VecSeq Inst ref construct-proxy agent-errors *compile-files* *math-context* set-agent-send-off-executor! ref-history-count cast parse-double EMPTY-NODE future? agent-error future-cancelled? struct-map stream-seq! mix-collection-hash ->Vec file-seq agent set-validator! tap> sync *compile-path* release-pending-sends print-ctor clear-agent-errors proxy-super add-classpath iteration accessor infinite? partitionv-all error-handler proxy-name find-protocol-method find-keyword send-off load-file extenders ->ArrayChunk ->VecNode abs ref-max-history Throwable->map parse-uuid io! update-keys *agent* *repl* *fn-loader* parse-boolean send proxy-call-with-super *compiler-options* get-proxy-class update-proxy create-struct get-validator await-for parse-long init-proxy future-cancel commute}
i suspect most but not all of these are intentional

jyn 2025-08-17T03:13:47.739019Z

hm, i tried to add these to src/sci/impl/namespaces.cljc but i kept getting errors like "Exception in thread "main" java.lang.RuntimeException: Unable to resolve symbol: update-keys in this context, compiling:(sci/impl/namespaces.cljc:1667:19)". i'm just going to post a list of the bindings i tried to add: • println-str • read+string (wasn't sure how to implement this so i just left a comment) • abs • infinite? • iteration • NaN? • parse-boolean • parse-long • parse-double • partitionv • partitionv-all • splitv-at • update-keys • update-vals • with-precision (wasn't sure how to implement this since it's a macro) i tried to be very conservative; i didn't include anything related to parallelism, transactions, agents, IO, UUIDs, or things that looks related to the state of the clojure interpreter; nor anything that wasn't documented.

jyn 2025-08-17T03:40:36.704799Z

hm also (/ 0.0 0.0) throws an exception in an SCI context instead of returning NaN, not sure if that's intentional

borkdude 2025-08-17T07:36:11.365849Z

Please one thing at a time. The reason update-keys isn't there is that SCI also works with older versions of clojure

borkdude 2025-08-17T07:36:27.810509Z

you can add it yourself in the 'clojure.core namespace per regular configuration. Also see babashka

👍 1
borkdude 2025-08-17T07:38:00.175769Z

The difference you are seeing with / is because of this differnce in Clojure:

user=> (/ 0.0 0.0)
##NaN
user=> (#'/ 0.0 0.0)
Execution error (ArithmeticException) at user/eval3 (REPL:1).
Divide by zero

borkdude 2025-08-17T10:37:05.465939Z

here is a configuration for clojure 1.11: https://github.com/babashka/sci.configs/blob/main/src/sci/configs/clojure_1_11.cljc

borkdude 2025-08-17T11:09:50.860529Z

Dilemma: In CLJS accessing properties with (.-foo-bar ...) actually gets munged to (.-foo_bar ...) But in SCI (.-foo-bar ...) is basically executed as (unchecked-get .... "foo-bar") This creates an divergence from CLJS. When one writes a script in nbb or scittle that uses (.-foo-bar ...) it will work on #js {:foo-bar ...} objects, but once a person ports this script to normal CLJS, you'll have to report to unchecked-get to make it work. So.. should this be fixed in SCI to align with CLJS? If we change this, then existing scripts might break. I have a branch of clj-kondo that lints whether your property access or method calls are subject to munging. This might help as well.

borkdude 2025-08-17T11:09:58.307319Z

🧵

p-himik 2025-08-17T11:55:02.094659Z

If it's fixed, there might be a bit of pain that eventually goes away. If it's never fixed, there's already a different kind of pain that will never go away. If it's put behind a potentially obligatory feature flag, it becomes a "choose your own adventure" kind of pain. E.g. :dashes :to-underscore would convert a-b into a_b (as a bonus you can use :-2_ instead of :to-underscore if you feel like the latter is a bit too long 🙂), :dashes :as-is would preserve the current behavior, and :dashes :warn would be the new default option that just complains when it encounters (.-a-b x).

borkdude 2025-08-17T12:12:33.652149Z

So what would be your favorite pain?

p-himik 2025-08-17T12:17:42.145789Z

Definitely the last. Doesn't break any existing code, does bring attention to the matter when there's something to pay attention to. Warnings could be annoying to some, but the cost-benefit with the other options still checks out.

borkdude 2025-08-17T12:37:49.816549Z

The :warn aspect of this I could include in clj-kondo, but it's still an optional linter since in CLJS only code it still causes false positives like

(deftype Foo []
  Object
  (foo-bar [_]))

(.foo-bar (->Foo))
I found several of such examples. Changing this all too:
(deftype Foo []
  Object
  (foo_bar [_]))

(.foo_bar (->Foo))
could be too much to ask for

p-himik 2025-08-17T12:45:59.967499Z

Hmm. deftype or defrecord are not something I have thought about. With that self-contained example, no warning is necessary at all - both versions are equally valid. But it seems that the first version could be problematic in some scenarios where JS interop is involved...

borkdude 2025-08-17T12:47:10.153889Z

Yep and it’s not clear from context what thing you are calling interop on

2025-08-17T13:05:45.999829Z

Here is my response just as a data point. I don't have a strong opinion on this. My main usage is Scittle (not nbb) and I feel everything is still quite greenfield. So I could tolerate a breaking change like this. Not sure if I would run into it myself. I like the idea of having Scittle as close to cljs as possible for potential migrations (for performance) or code sharing for libraries.

👍 1
➕ 1