Morning
has broken.
Bore da :welsh_flag:
I'm loving cgrand's xforms
morning!
Morning
Iβm loving data-driven UIs. I need to spec my UI-driving data more though!
morning!
moin moin
@orestis what are you using?
@otfrom Iβm using hx for the view layer, and my own reseda library for the state. https://github.com/lilactown/hx https://github.com/orestis/reseda
If anyone is interested, for those following the major.minor.commits approach to tagging repos, I've put together a very simple script to help do that. I use it on my clojure stuff all the time (with a slight variation, I prefix my versions with a rel/
)....
<https://gist.github.com/dharrigan/3e083f8d0fd0fc5646b6871d011a1e02>
Enjoy!
@otfrom https://twitter.com/borkdude/status/863792981198995456 (including nice comment by Ray!)
I do like monoids.
But Iβve also studied math.
I think not. A monoid is an associative operator with an identity element. (merge-with +)
is at most an associative operator.
Monoids are cool.
https://clojuredocs.org/clojure.core.reducers/monoid is a fascinating fn
drat. so close
@borkdude one could argue that maps form a monoid under merge with nil as the identity since
user> (merge nil)
;; => nil
user> (merge)
;; => nil
user> (merge {})
;; => {}
user> (merge {} nil)
;; => {}
user> (merge nil {})
;; => {}
user>
It seems like merge
has two identity values, nil
and {}
Monoids are just a very simple thing with a fancy name which makes people think they're smart when using it :)
conj
is also monoidic I believe
monoids are a datastructure + an operation + an identity element, not one or the other without any given context
Event though (conj)
=> []
, so it somewhat presents an identity value, it doesn't seem to form a monoid with []
as an identity value.
And, it's not really a binary operator of the same type
into
on the other hand, with []
as the identity seem to form a monoid.
(which makes sense since (reduce into [] colls)
)
Another (not really) interesting thing:
user> (clojure.repl/doc merge)
-------------------------
clojure.core/merge
([& maps])
Returns a map that consists of the rest of the maps conj-ed onto
the first. If a key occurs in more than one map, the mapping from
the latter (left-to-right) will be the mapping in the result.
;; => nil
user> (merge nil)
;; => nil
user> (map? nil)
;; => false
user>
So nil
is a map, but still it's not.
Things are monoids in clojure, except when Rich chose not to in an instanceof
check
Now, that's a tweet π
Feel free to tweet ;)
I'm not sure I grok the true meaning of it yet.
π€―
What I'm getting at is that some things are pretty ad hoc in Clojure based on their class. Take contains?
for example. Did you know that thing worked on String
?
What I find interesting with the typed fp folks is that they have their types and their "laws"
The "laws" are the things that the type-system can't help them with. It's where they have to retort to unit-tests
user=> (contains? "foo" 1)
true
Right, because strings are sequential?
or some such
nope, it's just hardcoded
Kind'a makes sense since Clojure is written pre-protocols and you can't extend interfaces to existing java-classes.
I think in hindsight they would not do the string seq / indexed thing again
could be wrong, but it feels like a mistake
I kind'a like it.
means you can use all the sequential fns on strings like interpose
, interleave
etc?
I've been told by Alex: please don't use seq on a string, but str/foobar
(e.g. str/blank?). It's just not an good idea to marshall a thing into some other object and then call some function on that which looks up if it's a string again, etc. All that waste of time
not really no, interpose doesn't return a string
No, it doesn't return a string, but you kan get it back by (I've forgotten how)
apply str?
yes, with horrible apply str + concat
(apply str (interpose \| "foo"))
"f|o|o"
exactly
Probably not something you'd do if you favour performance over golfing π
user=> (clojure.string/join "|" "foo")
"f|o|o"
(this calls seq on the string still)user> (apply str (interleave "aaa" "bbb"))
;; => "ababab"
user>
that's nice for 4clojure, but not something you typically do with strings
exactly. Neat but not useful
How did we get to here from monoids?
the thing with strings being seqables is that it leads to awkward core specs. like many functions take seqables, except strings
so then you need a different spec than ::seqable
which is annoying
yep
I'm just ranting, don't mind me ;)
But then maybe the problem is that the fns that take seqables should have accepted strings?
(apply str (remove #{\a} "blabla"))
is kinda nice
I mean, a string is just a sequence of characters so why bother implementing specific fns for it?
but then, maybe (into "" (remove #{\a} "blabla"))
should have been a thing.
oh maybe it was the nil
that was annoying
Which would make sense in a way, since map/filter/etc
aren't type-preserving anyway.
You're getting old. You can't remember why, just that you're annoyed π
The annoying thing is that clojure.string
fns blow up on nil π
I understand and accept why, but I'm still annoyed.
so nil is seqable? but can also be many other things. this annoyed me when creating the type system in clj-kondo, since it checks if something could have been of a certain type, so if something is nilable, it could have been a seqable....
dinner
btw @slipset, the type system in clj-kondo heavily borrowed from our core spec project :)
have a nice dinner
π© discovered today that queries are really slow if you have java util logging in with postgres. Was costing us 4x. I love the profiler we have in clojure, it's awesome.
How do you mean? Weβre you logging each query/result?
Postgres has built in logging
what does that have to do with java util logging though?
@slipset See https://github.com/borkdude/clj-kondo/blob/master/src/clj_kondo/impl/types/clojure/core.clj A lot of this resembles the speculative specs
Cool π
Thatβs a lot of workβ¦
That's what postgresql uses
huh.... b-b-but postgres is not written in java is it
Sorry, I mean the postgresql java driver!
I see now that I ignored that key term π long day as you can imagine
ah, right.
I usually enable the logging in postgres itself to see the queries
Yeah, I'm not sure what postgres is doing tbh