Fork me on GitHub

morning all


My colleagues don't know the Sex Pistols... 😞

😲 4

Cultural thing or an age thing? That is the question


Yesterday, had the awful realisation that most current university students were not born when the first Men in Black movie was released. :face_with_rolling_eyes:

😂 12
Ben Hammond09:02:28

but you have introduced them, presumably


It's a bit like recommending movies like Gattaca or The Shawshank Redemption

Ben Hammond09:02:27

as the ineptitude of Her Majesties Gubmint becomes more obvious I expect punk to reassert itself

🤞 8

punks not dead metal

👍 8
Ben Hammond09:02:14

anyone to got over the bland whinyness that's been in the charts for the last few years

Ben Hammond09:02:52

Ed Sheeran has had a few decent songs, but it mostly seems to be pap

Ben Hammond09:02:10

and that's a few more than Lewis Capaldi has had


I bitterly regret not having been a punk in the 70s. I was too busy being a revolting little swot. 😐

Ben Hammond09:02:48

Well they were quite scary


There are small lacunae of hope amidst the ocean of pap - Squid seem fairly close to punk. :thinking_face:


in this case it is an age thing. Mind you I am too young to have been there when Punk first came around.


Morning morning


I wish there was a when-let that had multiple bindings, but stopped at the first nil


There are couple of examples here of showing a when-let (macro) with multiple bindings


but, each binding gets evaluated (even if the nil occurs on the first binding)

Wes Hall11:02:57

I've also been bitten a few times by when-let style things when the value is literal false . It's so very intuitive to imagine that it short circuits at nil, but it short circuits on falsey and that can introduce a few tricky situations if you don't bare it in mind.


It's just that I want to avoid the triangle of death with lots of when-lets

Wes Hall11:02:02

Regular let and a single and is one route out of that pattern I guess.

Wes Hall11:02:32

I know what you mean though. I see a lot of this stuff. Never heard it called the "triangle of death" before, but it's an apt description.


I suppose and will work 🙂


there is when-some for only short circuiting nil


Does it only take one binding, like when?

Wes Hall11:02:34

@minimal I did not know that. Thanks. I find that I have a very poor memory for clojure.core api functions.


yeah i discover fns i have forgotten quite a lot

Wes Hall11:02:43

Yeah, I'm sure I did this a lot less in my Java days. One explanation for that is that I am getting older, but my current pet theory is that so many of the core functions are core functions are just compositions of the more base ones and once you get your head around how to use map, reduce etc, these become your goto solutions for everything. Maybe I should create a "function of the day" type app for myself, because I am sure my code would be cleaner if I knew more of the API by heart 🙂


@mccraigmccraig and I were talking about remembering stuff last year, I was giving myself a hard time for not immediately knowing the core API stuff. It’s okay not too, that’s what the docs are there for, it’s just knowing how to look when you’re working through the thought process.


when-some only does one let with and seems reasonable to use


also clojure.core is a massive bundle of disorganised stuff - java stdlib and ruby stdlib are both much easier to find stuff in because of some package hierarchy


and now i have N problems (where n=# of tag values) 😬


n can get pretty high before you arrive at the number of classes in Java's standard lib (or even packages for that matter).


i do agree it would be nice to be able to browse fns by a bunch of different axes, but I've also had a much nicer time browsing java and ruby stdlib docs than clojure.core docs, and the filesystem is always available whatever toooling you are using so i don't think i would want to lose a filesystem organised module/package structure, tho i wouldn't mind gaining additional browsable structures


I agree. As a newbie, it would be really great to have the core functions organised better. I'm very very sure, there are lovely functions in there that I could use, instead of me re-inventing the wheel due to ignorance.


There is this

Wes Hall11:02:40

Yeah, there is some doc somewhere that I used to use that broke down some of the functions in categories like, "if you have a collection and want a map, here are some functions..." etc etc. More of that would be quite useful I think.

Wes Hall11:02:54

Honestly, complaining about the problem of not having to memorise the entire core api before being productive is something for a first world problem anyway 🙂

Wes Hall11:02:24

"I'm sure there is a cleaner way to do this!" > "How on earth do I do this?" 🙂


I'm a big fan of this cheatsheet btw:


(oh, ha, I see that cheatsheet is a similar model, I think it didn't use to be; anyway the organisation by subject is 👌 esp for newbies)


the other thing that should be possible is adding fluency with flashcards, but then the question is, is it worth committing them to memory


you know, the transition from "I know it exists, let me look it up" -> "I can remember it and use with thinking" -> "I use it without thinking"


( eg. for me every variation of reduce/fold is "I can remember it and use with thinking" because in every f*n language, the order of arguments in reducer is different XD )


but you only have a limited amount of slots for things that you use without thinking... is it worth it?

Wes Hall11:02:54

@lady3janepl I do sometimes have the problem of finding myself feeling sure that there is a clean high-level function to achieve some goal, but failing to find it and doubting my own sanity.


the other option is, it's somewhere in metosin/potpuri or weavejester/medley


and it's so well-used that it looks like part of core 😄


"how to code" books should come with a health & safety warning about mandatory mental health checkups every x years...

Wes Hall12:02:06

Haha! Indeed.

Wes Hall12:02:02

Actually though, as I think about it. Probably the best way I found in my early clojure days was browsing other people's solutions to 4clojure challenges. That was definitely a good way to have a whole series of, "Oh, that's a nice way to do that!", moments.

Wes Hall12:02:17

Maybe it's because I haven't really done any of those in a while 🙂


Yup! I love reading other people's code

💯 4

there used to be an advent of code series focused on performance, that's been on my to-read list for some time 😄


but yeah, there's something satisfying about seeing an obvious solution, like art 🙂


I remember learning about things like second and partition after browsing other's solutions to exercism exercises

Wes Hall12:02:26

Here's an example of a common problem I have that feels like it should have a super clean solution, but where I always reach for reduce... build a map from a sequence by passing a key-fn and an val-fn. I am sure something like this exists, but I can never remember it.

(defn seq->map
  [s key-fn val-fn]
  (reduce #(assoc %1 (key-fn %2) (val-fn %2) {} s)) 


zipmap is my default for doing this: e.g. (zipmap (map kf coll) (map vf coll)) @minimal’s into juxt solution is cute though


I usually do something like (into {} (map (juxt key-fn val-fn)) s)


well i happened to do that on friday

Wes Hall12:02:05

Yeah, that solution crossed my mind also. These are all fine of course, but it's the kind of thing that sends me off searching the docs 🙂

Wes Hall12:02:17

I'm doing tonnes of these kinds of things right now. Working on a data migration so I would give rather a lot for Morpheus to put the kung-fu module down and inject me with the data-manipulation-fu module.

Wes Hall12:02:28

Though... i'll take the kung-fu one as well 😉


Well, I've just deployed another Clojure application into LIVE, replacing an equivalent Kotlin version....

👍 16
💪 4
Ben Hammond13:02:29

is the codebase significantly shorter?


Good question. Probably not, since the Kotlin version relys upon a lot of scaffolding given to you out-of-the-box via Spring Boot


So, I had to write code to collect to some services (like Elasticsearch) that are hidden from programmers using Spring Boot


(that's why I think people who use Spring Boot end up being Spring Programmers - sure, it's very very quick to spin something up, and the businesses love it, but from a cognitive point-of-view, trying to understand what your system does, it hides a lot of stuff)


More like Spring Butt, amirite


I find myself liking Spring less and less, we used Vert.x for our last project instead which I found better

Ben Hammond13:02:03

times have changed

Ben Hammond13:02:39

Spring was a total revelation back in 2005/2006 compared to the Enterprise Java evilitude that went before


Indeed, it was - I think I preferred it when all the config was in XML files.


The aspect-oriented programming stuff always felt like a mistake to me, though. Not keen on action at a distance or "magic".


I absolutely love Spring. But it's also impeding my Clojure studies, as I always end up choosing Spring for services because I can get them up and running so fast


But yes, some programmers are 'spring' programmers. Fortunately we have a lot of systems that are not Spring so I do get to work with Java without Spring


Spring feels to much like black magic for me.

Wes Hall15:02:11

Loved Spring for a very long time. "In Rod we trust", was a team motto on one of my teams back in the day 🙂. I am even a (fairly minor) contributor. It did get fairly bloated though. It's often a problem when this big open source projects try to find a commercial model, because it's always consulting and support and then suddenly your biggest clients want every feature they can imagine and everything becomes a mess. That said, the spring source code is still my go to example when somebody asks me what well-written Java looks like. There is a lot of features in there, but they do a pretty good job of keeping the code nice and clean.

Wes Hall15:02:08

The "aspectj" stuff by the way, really was fairly horrible black magic. I had less of a problem with the native AOP, because that was just basically OOP patterns. Delegation with a proxy.


Spring ha(d|s) some awesome class names - e.g. AbstractAnnotationConfigDispatcherServletInitializer , but I think my favourite is possibly HasThisTypePatternTriedToSneakInSomeGenericOrParameterizedTypePatternMatchingStuffAnywhereVisitor.


is this for real


It is (though as Wes points out, technically part of AspectJ rather than Spring core).


still ouch 😄

Wes Hall15:02:24

That was aspectj as I recall 🙂


Technically, yes. 🙂

Wes Hall15:02:38

The Spring names were a bit verbose, but this wasn't too bad. At least you could look at the name and understand essentially what the thing did.

Wes Hall15:02:03

I used it so much that that first name immediately parses in my head as three parts Abstract / AnnotationConfig / DispatcherServletInitializer


True - they were descriptive, so long as you were "in tune" with the Spring domain.


Yeah, I don't touch aspectj, don't understand why anybody would.

Wes Hall15:02:23

It was one of those things that was all the rage for a couple of years. Like SOAP.

Wes Hall15:02:33

I can remember when people started talking about, "cross cutting concerns", and I was like, "somebody is going to invent something messy to deal with this idea" 🙂


I've got a sad little graveyard of books on the WS-* stack. Haven't looked at them in years. :face_with_rolling_eyes: Haven't missed them, either.

Wes Hall15:02:48

The best thing about SOAP was opportunity for humour. I went to a trade show once and on the book stall they had a copy of, "Understanding SOAP", and when I picked it up and opened it, somebody has scrawled, "A beginners guide to personal hygiene" on the first page. I laughed quite hard and then had to convince the guy running the stall that it wasn't me that did it.

😂 12

eh. everyone's kind of trying to recreate soap with swagger/openAPI


but this time - in JSON! so you can't even add comments.

Wes Hall15:02:48

Also, when I joined eBay my first little induction project was to write this cluster listener thing that would add / remove services to the hardware load balancer on cluster autoscaling events. The LB API was SOAP but while I tried every single Java SOAP library I could find. None of them seemed to produce the format required for these stupid things. Eventually I figured out that the easiest solution was just to make a velocity template from a sample envelope because of the 10'000 or so characters in the actual XML, only 20 or so were actually meaningful. So I copy pasted the example into a template, set up a couple of variables to change the tiny part that needed to change (IP and port params), and did it all with velocity templates. Worked perfectly, but a great example of how pointless most of that stuff was.

👍 12

Does anyone here use Transit? It never seemed to gain much of a following.


We (where I work) use transit with metosin/muuntaja and r0man/cljs-http. And it is almost transparent to the devs..

👍 4

I believe it is quite widely adopted when using cljs with a clj backend. EDN isn’t ideal as a transfer format for large quantities of data, as it’s quite slow to parse, and is several orders of magnitude slower than parsing JSON in the browser or in many interpreted languages; because they can leverage a native JSON parser for JSON but not EDN. Transit’s main serialisation format is built on top of JSON, so it has comparable performance to JSON parsing in these environments; and obviously has first class support for clojure’s datastructures.


I can confirm it is 2 orders of magnitude faster in cljs on node. There are bench marks in the cljs-transit repo here: Though there are no numbers, it’s pretty straightforward to run them… Here’s my output (note I tweaked the second to last println as there is a bug in the originals output).

10:21 $ node target/transit.bench.js 
100 iters, JSON.parse seattle data
"Elapsed time: 68.000000 msecs"
100 iters, transit read seattle data
"Elapsed time: 95.000000 msecs"
100 iters, JSON.stringify seattle data
"Elapsed time: 38.000000 msecs"
100 iters, transit write seattle data
"Elapsed time: 255.000000 msecs"
100 iters, transit write seattle data no-cache
"Elapsed time: 185.000000 msecs"
100 iters, read-str seattle data
"Elapsed time: 2604.000000 msecs"
100 iters, pr-str seattle data
"Elapsed time: 437.000000 msecs"


so reading transit is 95ms where as reading the same data as EDN is 2.5s!!


Many thanks for the detail on this - that's certainly a substantial speed-up! Glad to know that Transit is still very much a going concern! I experimented with it when it was "new" (in the scenario you cite - cljs front end / clj back), but hadn't heard much mention of it since that time.

Wes Hall15:02:48

No, not really used it. Did take a look but I tend to think that human-readable wire protocols have some advantages and never really found myself in a situation where that seemed worth sacrificing for a little extra processing and/or bandwidth performance.

Wes Hall15:02:13

I'd definitely prefer EDN over JSON, but all these PERL-like characters for data typing....


Quite - I tend to go with EDN.

👍 4

If you're using fulcro or shadow-cljs, you're probably communicating via transit. 😉 So I wouldn't say it has not gained much of a following. Not sure how alive it is outside of Clojure-land, though.


Ah - haven't yet dipped my toe into shadow-cljs!


I keep meaning to give it a whirl, to see what if offers as compared with Figwheel / Devcards.


@rhinocratic we use transit in one place - as a serialisation format for database dumps - iirc it's extensibility and performance are both better than EDN (which we used for a while, but ran out of steam with). EDN is our goto though

👍 4

re: trek and politics


the ds9 stuff with strike breaking and the security chief was ace


and the suicide bombing plot in battlestar (plus the torture bit that ref’d abu grahib) was smartly done and timely I thought


idk, I think that these things could be bashing people over the head a bit but you’re also playing to a broad audience, some of whom are thick and need it spelling out a bit


but if you can make people of all walks of life provoked to think about stuff ’cos of philosophy in spaaaaaace! then wth not i say

prosper 8

@rhinocratic has just reminded me that I need to finish my shadow-cljs/re-frame workshop code for the next LL mcr


maybe on the train tonight, depends if we’re feeling energetic…


Must go along to that - ages since I attended a LL meeting. Been languishing in .Net land of late, but still hope to change that.