Fork me on GitHub
#squint
<
2023-12-09
>
borkdude11:12:24

I discovered yesterday that the bloomberg polyfill for TC39 records and tuples makes equality work by interning all immutable objects in a weakmap, so they are really one and the same when you instantiate a second one. Now I get why they say "explicitly not for production" 😅

pez11:12:03

What does it mean “interning all immutable objects in a weakmap”?

borkdude11:12:37

when creating an immutable object, they check if there is already one like it in their weakmap and then return that one, else create it for the first time

borkdude11:12:04

a weakmap is a map whose elements can be garbage collected if necessary (when memory runs out)

borkdude11:12:37

keywords work the same way in JVM Clojure

borkdude11:12:46

except they do it with all collections

borkdude11:12:24

it's fine for doing AOC puzzles and some other cases, but it's good to be aware of this implementation which is not the most efficient

pez11:12:02

I think I saw somewhere that Rich Hickey explained a bit how value equality is tested for in Clojure. Can’t recall where right now, and not the details either, but I remember it sounded very sensible and efficient.

borkdude11:12:38

yes, but the issue in JS is that you can't override = so I think they didn't have much choice in this polyfill

✅ 1
borkdude12:12:59

pushed

🙏 1
pez12:12:40

How did you find it? /Curious George

borkdude12:12:53

I didn't find it, I just thought about it

pez12:12:04

Fore clojure.set there is index and join left to implement. I started with index to build my self confidence. However, given how we do not have value semantics I wonder
 And my first straight port fails in a predictable way. -> đŸ§”

pez12:12:10

(set/index #{{:name :betsy :weight 1000}
               {:name :jake :weight 756}
               {:name :shyq :weight 1000}}
    [:weight])
=>
Map(3) {
  { weight: 1000 } => Set(1) { { name: 'betsy', weight: 1000 } },
  { weight: 756 } => Set(1) { { name: 'jake', weight: 756 } },
  { weight: 1000 } => Set(1) { { name: 'shyq', weight: 1000 } }
}

borkdude13:12:21

what is wrong about this?

pez13:12:22

This is the code:

export function index(xrel, ...ks) {
  return core.reduce((m, x) => {
    const ik = core.select_keys(x, ...ks);
    const xs = core.get(m, ik, new Set());
    return core.assoc(m, ik, core.conj(xs, x));
  }, new Map(), xrel);
}

borkdude13:12:30

yeah this isn't suited for JS collections. To be fair, I've never used set/index anywhere, let's just leave it out to not create a trap

borkdude13:12:23

with TC39 records and tuples it would work like you would expect

borkdude13:12:26

but we haven't got those yet

pez13:12:25

Makes sense.

borkdude13:12:21

The index-by function from medley is way more useful than this one imo

pez13:12:16

Would be a fun project to port the most useful medley functions 😃

borkdude13:12:38

or rather group-by:

I found group-by doesn't do toFn yet, I'll fix that on main

pez13:12:08

What’s the significance of toFn?

borkdude13:12:24

keywords in squint are just strings and toFn turns a string into #(get % the-string)

borkdude13:12:33

such that (group-by :foo ...) works

borkdude16:12:19

heck yeah!

🎉 1
borkdude11:12:38

in case you lost track, there's 2 more comments to address in the PR

borkdude11:12:57

oh you got them

pez11:12:38

I hope I’ve got it all addressed now.

borkdude11:12:58

two more, one is pretty essential else we'd get a reverse performance problem :)

pez11:12:16

👀

borkdude11:12:33

intersection requires to start with the smallest set, not the biggest

borkdude11:12:44

this is why we pass the negative count function

pez11:12:46

Good catch! Thanks!

borkdude11:12:41

@pez cool. I made another PR with some optimizations https://github.com/squint-cljs/squint/pull/433

borkdude11:12:51

which miraculously doesn't have conflicts with the previous one

pez11:12:22

squint is such a crazy and wonderful idea.

borkdude11:12:51

thank you :)

pez16:12:20

What’s up with quote?

(quote foo) => TypeError: Cannot read properties of undefined (reading 'core')

borkdude17:12:06

return globalThis.user.cljs.core.symbol("foo");
symbol doesn't exist in squint

borkdude17:12:32

quote works, symbol doesn't

pez17:12:48

Ah, I’ll try to understand this a bit now. 😃

borkdude17:12:48

what are you trying to understand?

pez17:12:02

The implications of that symbols doesn’t exist.

borkdude17:12:05

symbols are mostly used for representing forms in macros

borkdude17:12:22

they can be used in macros since macros are ran in SCI

borkdude17:12:33

and cherry does have symbols and keywords

pez17:12:35

If I (def foo :foo) in squint, what am I evaluating when I later evaluate foo?

pez17:12:41

I’m not suggesting symbols should exist, I’m merely trying to reprogram my brain which insists on symbols being a thing.

borkdude17:12:18

unquoted symbols in clojure always resolve to a value

mynomoto18:12:57

Is flatten missing from squint? I just read the squint readme, I had no idea of what I was using until now, for me it was just like clojurescript. Now @borkdude message about sets on a #C0GLTDB2T thread makes sense 😅

😂 2
borkdude18:12:23

ah yes, we can add flatten, I ran into that as well

seancorfield18:12:36

flatten is nearly always the "wrong" answer so maybe it's good that it isn't present? :rolling_on_the_floor_laughing:

mynomoto18:12:57

@U04V70XH6 not for advent of code 😉

borkdude18:12:07

@U05094X3J if you change /squint/ in the url bar to /cherry/ then you will switch to cherry and this has flatten

borkdude18:12:14

I'll add it just for compatibility though

mynomoto18:12:33

But in this case it would really be wrong :rolling_on_the_floor_laughing: