sci

2024-02-02T10:55:22.279109Z

A port of Clojurescript Koans using SCI. Thank you, @borkdude, to make that possible. gratitude

borkdude 2024-02-02T10:55:38.795989Z

Amazing work, thank you

2024-02-02T11:01:13.838549Z

I have a confession, I tried to change as little as possible, so I first attempted to use self-hosted Clojurescript. But after trying to make it work using an updated Clojurescript and shadow-cljs I gave it up and decided to port to SCI. It took less time to convert to SCI than the time I used to try to use self-hosting. Also, I can use advanced compilation, and the SCI version is way smaller than the Clojurescript one. SCI is an incredible tool.

borkdude 2024-02-02T11:03:35.445979Z

great to hear. there's another option emerging for this kind of use case, it's the cherry compiler that can be embedded: https://github.com/squint-cljs/cherry/blob/main/doc/embed.md but it's less mature than SCI (simply because it's newer) - the only benefit of that is better performance (which should not matter for a tool that teaches how to use Clojure)

2024-02-02T11:07:05.706799Z

More options are great! I will check it out, but the current bundle size is enough, so I will probably keep on the more mature tool. Does SCI track clojure or clojurescript when there are different behaviors? I found some differences from clojure while I was writing some lessons on another project.

borkdude 2024-02-02T11:13:54.145449Z

SCI doesn't track clojure or clojurescript unless there are new behaviors like the one with keyword arguments vs passing a map. This is so that SCI can be used with older version of Clojure as well. Right now it supports 1.9

borkdude 2024-02-02T11:14:08.848219Z

Which differences with Clojure did you find?

2024-02-02T11:16:43.907239Z

Only corner cases, like calling max without arguments. Cases where Clojure returns exceptions, I think. I haven't checked the Clojurescript behavior yet to confirm that it is the same.

borkdude 2024-02-02T11:17:57.545279Z

The max function isn't re-implemented so that would surprise me

borkdude 2024-02-02T11:18:20.879729Z

$ bb -e '(max)'
----- Error --------------------------------------------------------------------
Type:     clojure.lang.ArityException
Message:  Wrong number of args (0) passed to: clojure.core/max

borkdude 2024-02-02T11:19:21.433219Z

The CLJS version only throws because max in call position is implemented using a macro. What happens in SCI is more like:

plk -e '(let [m max] (m))'

borkdude 2024-02-02T11:19:24.895499Z

which doesn't throw

2024-02-02T11:19:28.448079Z

Let me pick a real one instead of trying to use my memory 😅

2024-02-02T11:20:35.444439Z

subs throws in clojure with index out of bounds when using an index larger than the string size.

borkdude 2024-02-02T11:21:06.286899Z

also not re-implemented. it's probably just a CLJS vs CLJ difference

2024-02-02T11:23:59.849079Z

Ok, so when are cases like this it should behave like Clojurescript except when there is a macro implementation?

borkdude 2024-02-02T11:24:21.625489Z

yes, test it like: (let [f subs] (f ...))

borkdude 2024-02-02T11:25:00.264339Z

btw in CLJS:

$ plk -e '(subs "" 0 11)'
""

borkdude 2024-02-02T11:25:51.987449Z

of course if you wanted to, you could override subs in clojure.core with your own:

{:namespaces {'clojure.core {'subs ...}}}
`

2024-02-02T11:28:11.771909Z

Yeah, I suspected that was the case (that it behaved like in cljs). Thank you, I need to think if I would go that far, not really sure if it is necessary. I would just show an example throwing, so the user would not be surprised when it happened. There will be other exceptions that I can use 😉

Ingy döt Net 2024-02-02T19:13:57.442889Z

Are parse-* not available by default for sci/eval-string?

borkdude 2024-02-02T19:21:22.898879Z

what do you mean exactly, parse-what?

Ingy döt Net 2024-02-02T19:21:52.420279Z

Sorry. parse-long parse-double

borkdude 2024-02-02T19:22:37.695229Z

ah gotcha. not by default since sci goes back to clojure 1.9. pretty easy to add yourself though

Ingy döt Net 2024-02-02T19:24:05.280409Z

yep, ok thanks. Is there a writeup somewhere about what things went into (or didn't) sci defaults and why?

Ingy döt Net 2024-02-02T19:24:58.674619Z

it would be good for me to respect some of the same decisions, but I don't have the background rationale

Ingy döt Net 2024-02-02T19:27:52.503769Z

added the parse-* just now. was indeed trivial 🙂

borkdude 2024-02-02T19:28:50.159129Z

It just supports the functions that are in 1.9 and doesn’t support any functions that are deemed unsafe for sandboxing

borkdude 2024-02-02T19:28:59.468159Z

Like spit etc

Ingy döt Net 2024-02-02T19:30:36.617839Z

yeah, that's mostly what I wish I knew. what's safe to eval wrt arbitrary input. did you just figure that out over time?

borkdude 2024-02-02T19:32:40.841879Z

you can take a look at what babashka adds compared to SCI and then you'll know

Ingy döt Net 2024-02-02T19:33:20.415109Z

ok