squint 2025-10-17

~{} returns -1 in JavaScript, don't ask me how I know

😵‍💫 3

> ~"foo"
-1
> ~NaN
-1
> ~["foobar"]
-1
seems to do the same for all non-numbers?

I can't recall ever using ~ operator in JS

well, ~{} is used in js* ;)

Work in progress but got this working:

(get (assoc {} :a 1) :a)
=>
{ ...{}, a: 1 }["a"]
It can be inferred that {} is an object, so both assoc and get compile down to low level JS

😍 1
🎉 2

oh you could probably do the same for conj and vectors - in my datastar-expr library I had these implemented in terms of merge and concat (I had the benefit of assuming an even thinner translation barrier than squint's and narrowing the semantics of these functions, ie no clever inference needed)

(mapv emit `[(merge) (merge m1) (merge m1 m2)
             (concat) (concat v1) (concat v1 v2)])
;; => ["{}" "{...m1}" "{...m1,...m2}"
;;     "[]" "[...v1]" "[...v1,...v2]"]


(mapv emit `[(merge m {:a 1}) (merge {:a 1} m) (merge {} m {})
             (concat xs [1 2 3]) (concat [1 2 3] xs) (concat [] xs [])])
;; => ["{...m,'a':1}" "{'a':1,...m}" "{...m}"
;;     "[...xs,1,2,3]" "[1,2,3,...xs]" "[...xs]"]

(emit `(assoc m :k1 v1 k2 v2)) ;; => "{...m,'k1':v1,[k2]:v2}"
(emit `(conj xs 1 2)) ;; => "[...xs,1,2]"
(emit `(cons 1 xs)) ;; => "[1,...xs]"
(emit `(list* 1 2 3 xs)) ;; => "[1,2,3,...xs]"

(emit `(get (assoc {} :a 1) :a)) ;; => "({'a':1}).a"

yes, planning to do that next

✨ 1

yeah thanks for the merge idea, that's neat

I mean, only the merge and concat ones, the rest isn't going to work in squint since it has a distinct list type

yeah I guess it depends how faithful to clojure's semantics you want to be re. concat returning a lazy seq

(oh nice, I realised my current impl for (get m k nf) => "m[k]??nf" , the in operator is definitely a better way to go)

Drag-and-drop example that I wrote 9 years ago in Reagent, now in Eucalypt: https://squint-cljs.github.io/squint/?src=KG5zIGRlbW8KICAoOnJlcXVpcmUKICAgWyJodHRwczovL2Nkbi5qc2RlbGl2ci5uZXQvbnBtL2V1Y2FseXB0QDAuMC4xNC8rZXNtIiA6YXMgcl0pKQoKKGRlZiBibGFjay1ob2xlLXBvcyB7OnggNDAwIDp5IDQwMH0pCgooZGVmIGRyYWdnYWJsZSAoci9hdG9tIHs6eCAxMDAgOnkgMTAwIDphbGl2ZT8gdHJ1ZX0pKQoKOzsgVXRpbGl0eSBmdW5jdGlvbnMKKGRlZm4gY2xvc2U%2FIFt4IHldCiAgKGFuZCAoPCAoTWF0aC9hYnMgKC0geCAoOnggYmxhY2staG9sZS1wb3MpKSkgNTApCiAgICAoPCAoTWF0aC9hYnMgKC0geSAoOnkgYmxhY2staG9sZS1wb3MpKSkgNTApKSkKCgooZGVmbiBnZXQtY2xpZW50LXJlY3QgW2V2dF0KICAobGV0IFtyICguZ2V0Qm91bmRpbmdDbGllbnRSZWN0ICguLXRhcmdldCBldnQpKV0KICAgIHs6bGVmdCAoLi1sZWZ0IHIpLDp0b3AgKC4tdG9wIHIpfSkpCgo7OyBFdmVudCBoYW5kbGVycwooZGVmbiBtb3VzZS1tb3ZlLWhhbmRsZXIgW29mZnNldF0KICAoZm4gW2V2dF0KICAgIChsZXQgW3ggKC0gKC4tY2xpZW50WCBldnQpICg6eCBvZmZzZXQpKQogICAgICAgICAgeSAoLSAoLi1jbGllbnRZIGV2dCkgKDp5IG9mZnNldCkpXQogICAgICAoaWYgKGNsb3NlPyB4IHkpCiAgICAgICAgKHJlc2V0ISBkcmFnZ2FibGUgezphbGl2ZT8gZmFsc2V9KQogICAgICAgIChyZXNldCEgZHJhZ2dhYmxlIHs6eCB4CiAgICAgICAgICAgICAgICAgICAgICAgICAgIDp5IHkKICAgICAgICAgICAgICAgICAgICAgICAgICAgOmFsaXZlPyB0cnVlfSkpKSkpCgooZGVmbiBtb3VzZS11cC1oYW5kbGVyIFtvbi1tb3ZlXQogIChmbiBbZXZ0XQogICAgOzsgcmVtb3ZlIHRoZSBtb3VzZW1vdmUgbGlzdGVuZXIKICAgICgucmVtb3ZlRXZlbnRMaXN0ZW5lciBqcy93aW5kb3cgIm1vdXNlbW92ZSIgb24tbW92ZSkpKQoKKGRlZm4gbW91c2UtZG93bi1oYW5kbGVyIFtlXQogIDs7IGdldCBib3VuZGluZyByZWN0IG9mIHRoZSB0YXJnZXQgZWxlbWVudAogIChsZXQgW3s6a2V5cyBbbGVmdCB0b3BdfSAoLmdldEJvdW5kaW5nQ2xpZW50UmVjdCAoLi10YXJnZXQgZSkpCiAgICAgICAgb2Zmc2V0IHs6eCAoLSAoLi1jbGllbnRYIGUpIGxlZnQpCiAgICAgICAgICAgICAgICA6eSAoLSAoLi1jbGllbnRZIGUpIHRvcCl9CiAgICAgICAgOzsgZGVmaW5lIHlvdXIgbW92ZSBoYW5kbGVyICh5b3UgYWxyZWFkeSBoYXZlIGl0KQogICAgICAgIG9uLW1vdmUgKG1vdXNlLW1vdmUtaGFuZGxlciBvZmZzZXQpXQogICAgOzsgYWRkIG1vdXNlbW92ZSBsaXN0ZW5lcgogICAgKC5hZGRFdmVudExpc3RlbmVyIGpzL3dpbmRvdyAibW91c2Vtb3ZlIiBvbi1tb3ZlKQogICAgOzsgYWRkIG1vdXNldXAgbGlzdGVuZXIgdGhhdCByZW1vdmVzIHRoZSBtb3VzZW1vdmUKICAgICguYWRkRXZlbnRMaXN0ZW5lciBqcy93aW5kb3cgIm1vdXNldXAiIChtb3VzZS11cC1oYW5kbGVyIG9uLW1vdmUpKSkpCgo7OyBDb21wb25lbnQKKGRlZm4gZHJhZ2dhYmxlLWJ1dHRvbiBbXQogIFs6ZGl2CiAgIFs6aDEgKHByLXN0ciBAZHJhZ2dhYmxlKV0KICAgWzpidXR0b24uYnRuLmJ0bi1kZWZhdWx0CiAgICB7OnN0eWxlIHs6ei1pbmRleCA4CiAgICAgICAgICAgICA6cG9zaXRpb24gImFic29sdXRlIgogICAgICAgICAgICAgOmxlZnQgKHN0ciAoOnggYmxhY2staG9sZS1wb3MpICJweCIpIDsKICAgICAgICAgICAgIDp0b3AgKHN0ciAoOnkgYmxhY2staG9sZS1wb3MpICJweCIpCiAgICAgICAgICAgICA6YmFja2dyb3VuZCAiY29sb3I6IGJsYWNrOyJ9fQogICAgIk5vdCBoZXJlIHBsZWFzZSJdCiAgIChpZiAoOmFsaXZlPyBAZHJhZ2dhYmxlKQogICAgIFs6YnV0dG9uLmJ0bi5idG4tZGVmYXVsdAogICAgICB7OnN0eWxlIHs6ei1pbmRleCA4CiAgICAgICAgICAgICAgIDpwb3NpdGlvbiAiYWJzb2x1dGUiCiAgICAgICAgICAgICAgIDpsZWZ0IChzdHIgKDp4IEBkcmFnZ2FibGUpICJweCIpIDsKICAgICAgICAgICAgICAgOnRvcCAoc3RyICg6eSBAZHJhZ2dhYmxlKSAicHgiKX0KICAgICAgIDpvbi1tb3VzZS1kb3duIG1vdXNlLWRvd24taGFuZGxlcn0KICAgICAgIkRyYWcgbWUiXSldKQoKKHIvcmVuZGVyCiAgW2RyYWdnYWJsZS1idXR0b25dCiAgKG9yCiAgICAoanMvZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQgImFwcCIpCiAgICAoZG90byAoanMvZG9jdW1lbnQuY3JlYXRlRWxlbWVudCAiZGl2IikKICAgICAgKGFzZXQgImlkIiAiYXBwIikKICAgICAgKGpzL2RvY3VtZW50LmJvZHkucHJlcGVuZCkpKSk%3D

Every time I see a Eucalypt example I have the same feeling: "I can't believe this works".

➕ 1

oh, I think I found a bug in take-last? negative numbers should return (), I'm not sure what the Math.abs is doing there https://squint-cljs.github.io/squint/?repl=true&src=KHRha2UtbGFzdCAtMSBbMSAyIDMgNCA1XSk%3D