squint 2024-08-16

I had a stupid idea. Some people asked if we could use @ for js-await but this won't work since js-await is a special built-in thing which will make functions async if you use it, unlike deref. But we could use as a shorter notation, inspired by core.async. Although I'm not convinced that a few characters will make the difference.

(-> (js/fetch "") 

I have to admit that just from looking at the two snippets, what I find more confusing is that it’s js-await and not js/await

It used to be js/await but for good reasons this has been changed to js-await : • js/foo is used to point at global JS objects/functions. however, await is not an object or function, it is special JS syntax • for special JS syntax, the convention js-foo is used in ClojureScript. E.g. js-delete , js-keys , js-in . Hence js-await

👍 1

thanks for explaining 🙂 I guess it would become second nature if I used this more… need to find a way to do so

Does using js-await inside of a function automatically async that function? E.g.

(defn ^:async foo []
  (js-await (bar)))
and
(defn foo2 []
  (js-await (bar)))
are identical in functionality?

no, you have to mark foo2 as async, or it's going to be a JS error, just like in JS itself

What do you mean by js-await is a special built-in thing which will make functions async if you use it ?

I mean in JS await is a special syntax

and in squint js-await just compiles to await

Ah right, I think I misread there

in JS you have to use the async keyword for a function as well, if you're using await or else you're going to have an error

I thought maybe you were suggested that there was some magic added to the defn macro in squint that checked the body for js-async

well, there is some magic but functions aren't magically turned into async, I think that would lead to nasty surprises, better to be explicit

e.g. let expressions use IIFEs when compiled to JS and those are automatically async

so you can use js-await in let

(switch to non-REPL mode for cleaner code)

Personally I would avoid overloading @ or <! with new meaning that is similar but not quite the same and come up with some new character sequence like <p or @w or something.

<! Isn’t an existing thing in core, just core async so it’s not overloading necessarily, but I won’t anyway

what's wrong with extend-protocol atm?

I don’t think there Iassosiative etc at the moment to which assoc reacts

That would be awesome! I'm using immutablejs and squint heavily in my web app-startup!

I guess if I'd make extend-protocol etc work more reliable in squint, I could make assoc et al work with immutablejs in a "transparent" way

3

I haven't totally rejected the idea, but still thinking about pros / cons. One con is that if assoc etc have to check the object for protocol impl, it's a small perf cost

I thought more about this. It would make sense for squint that the "contract" of the standard library is that assoc, etc return a ready to be used JS object without having to go through some conversion (as it the case with immutable-js)

Got this working locally (and in branch assoc-protocol):

$ ./node_cli.js -e "(require '[\"immutable$default\" :as imm]) (extend-type imm/Map IAssociative (-assoc [m k v] (.set m k v)))  (-> (new imm/Map [[1 2]]) (assoc :foo :bar 1 2 3 4) .toJSON js/console.log)"
{ '1': 2, '3': 4, foo: 'bar' }
Not sure how far we want to push this though. For example = currently always just compiles to JS === and there isn't an -equiv protocol, so comparing ImmutableJS hashmaps still has to be done manually, which kind of defeats the purpose of not dealing with immutableJS literally

so perhaps it's better to just be explicit in using immutablejs

hmm. yes, that makes sense.

I use Squint (over ClojureScript) because of the performance benefits. I would be happy to see it going "lightweight" path.

I think it might be OK to treat IAssociative and equality as separate. you already have to compare JS objects manually if you can't rely on new reference => new value

yeah I was also thinking that

perhaps we can introduce an equiv protocol with an explicit equiv function for value equality

which you should use in squint rather than using = for value equality

not sure how much that would buy you

my question in general is: how much does extending core functions to protocols buy you vs writing your small idiomatic clojure wrapper around immutable-js (e.g. imm/assoc, imm/dissoc etc

I see value because it facilitates the possibility of porting your app to full clojurescript and throwing away immutablejs down the road.

that's true, but never 100% right

you could also reach that goal by doing this:

(ns foo (:require [#?(:squint my-immutable-wrapper :cljs cljs.core) :as imm]))

(imm/assoc ..)

😎 1

perhaps = isn't as important in general since in Clojure you mostly rely on something being a subset since more keys are generally not a problem

but now I'm rationalizing

The qu on the back of the shirt could work nicely as a slack emoji, I think.

Hmmm, maybe it got a bit destroyed… Kan @tonsky make a special icon for this maybe?