clojure-europe

For people in Europe... or elsewhere... UGT https://indieweb.org/Universal_Greeting_Time
dharrigan 2020-10-29T06:44:57.472400Z

Dia Duit!

ordnungswidrig 2020-10-29T07:21:07.472600Z

🙂

RAMart 2020-10-29T07:46:45.472900Z

☀️

thomas 2020-10-29T07:57:55.473100Z

moin moin

javahippie 2020-10-29T08:13:59.473400Z

Tach!

🥦 1
ordnungswidrig 2020-10-29T08:28:28.473800Z

2020-10-29T08:41:39.474400Z

bon jour!

dominicm 2020-10-29T08:51:54.474600Z

Morning

raymcdermott 2020-10-29T08:57:07.475200Z

I’m in a reflective mood today, good morning

2020-10-29T12:14:45.475700Z

boom boom

ordnungswidrig 2020-10-29T13:52:45.475900Z

who’s there?

borkdude 2020-10-29T15:28:23.476100Z

There's a Clojure thread on Hacker news front-page now :)

2020-10-29T16:00:29.476400Z

oh no

2020-10-29T16:00:48.476800Z

as long as comp.lang.lisp stays away

2020-10-29T16:00:50.477Z

😉

borkdude 2020-10-29T16:03:35.477300Z

I can handle them 💪

2020-10-29T16:06:27.477700Z

I should stop being so mean

2020-10-29T16:06:43.478100Z

I blame too many years trying to learn lisp from comp.lang.lisp

borkdude 2020-10-29T16:08:06.479Z

Oh, I know what you mean, I was there in the early 2000s learning Common Lisp...

borkdude 2020-10-29T16:08:16.479200Z

Maybe I was that guy who offended you?

2020-10-29T16:09:07.479400Z

ooh... maybe

2020-10-29T16:09:38.480Z

I don't think so tho. I remember how offended everyone in c.l.l was about a lisp on the jvm that betrayed the lisp machine ideals

2020-10-29T16:09:53.480400Z

it was one of the happiest days of my programming career

2020-10-29T16:10:10.480800Z

a good lisp on the jvm with good interop so that I could use the java libs I already knew? Fantastic.

borkdude 2020-10-29T16:10:54.481600Z

For me Clojure was a way to learn about the JVM. I was only familiar with .NET and didn't like what I saw comparing the built-in date library and some more.

borkdude 2020-10-29T16:11:18.482100Z

But I needed to work with the JVM because I was a lecturer back then and these students were mostly taught Java

borkdude 2020-10-29T16:12:18.482600Z

Within a year or two I was running a Clojure course to teach them some next level programming :P

borkdude 2020-10-29T16:21:34.483100Z

I was lucky to avoid teaching OOP design patterns because I couldn't comfortably teach that while knowing the alternatives

borkdude 2020-10-29T16:23:06.483400Z

I mean, I would act neutral, but some things you can't easily hide

borkdude 2020-10-29T16:27:37.484800Z

I like it as an intellectual thing, but I don't like it from the perspective of writing boilerplate in a language you have to work towards freedom first

2020-10-29T16:28:30.485700Z

oh gods, the way people abused it was terrible, but actually understanding the patterns made it easier to think your way around a problem without having to invent everything yourself

2020-10-29T16:28:36.485900Z

I really liked builder

2020-10-29T16:28:51.486400Z

the clojure data structures seem to use the flyweight pattern

borkdude 2020-10-29T16:29:07.486800Z

yeah, you could apply some of those patterns in Clojure as well, but most of it is just plain common sense don't you think

2020-10-29T16:30:08.487400Z

I think they are often common sense, but that is why programmers would never know them 😉

2020-10-29T16:30:23.487700Z

I don't think most of them make sense in fp languages

2020-10-29T16:30:29.487900Z

they are very OOP

2020-10-29T16:31:05.488700Z

but for implementing fp languages in OOP languages (like clojure in java) I think they are probably pretty useful, just don't see them as things you can copy and paste from

borkdude 2020-10-29T16:32:06.489400Z

yeah, maybe put it too strongly, but these books of hundreds of pages of material which would almost be trivial in Lisp/FP, it didn't sit well with me

2020-10-29T16:34:07.489700Z

fair enough, but that is a problem with OOP not patterns

borkdude 2020-10-29T16:34:24.490Z

yes, I was referring to OOP design patterns specifically

2020-10-29T16:35:06.490400Z

I think with Language of the System that RH is reaching for some FP patterns

borkdude 2020-10-29T17:16:39.491600Z

Now that I'm ranting anyway: I wish core wouldn't have used the 2-arity of map, filter etc for transducer. I built a clj-kondo type system for it to reduce the amounts of errors I get because of mistakes I make with this.

borkdude 2020-10-29T17:17:12.492300Z

I had another one right now: there was a JSON payload that silently missed a field, turns out it was because a transducer could not be serialized, yeah, duh...\

borkdude 2020-10-29T17:17:35.492900Z

I would have preferred (mapping inc), (filtering odd?) over (map inc) and (filter inc) any time of day

jasonbell 2020-10-29T17:35:11.493100Z

Morning

2020-10-29T18:00:47.493400Z

morning Jade

2020-10-29T18:02:08.493600Z

the whole transduce thing of • arity 0 for initialise • arity 1 for finish • arity 2 for iteration seems like a really strange design choice to me

2020-10-29T18:02:28.493800Z

it would certainly be clearer to declare as a record

2020-10-29T18:03:19.494Z

the reason I can think of is that JVM is massively optimised for overloaded functions, and this was felt to outweight the confusing code implications?

2020-10-29T18:03:43.494200Z

Is there are more compelling reason that I have missed?

2020-10-29T18:04:11.494400Z

(Er is that what you were talking about...? Or I have missed the point?)

2020-10-29T18:17:34.495300Z

@borkdude thx for clj-kondo. It is making my refactoring to get around not being able to debug things a lot easier. Couldn't get through this w/o your tool.

2020-10-29T18:17:50.495600Z

(I'm basically coding by squiggly lines atm)

borkdude 2020-10-29T18:18:00.495700Z

My gripe was with (map inc) vs (map inc [1 2 3])

borkdude 2020-10-29T18:18:47.496Z

I would have preferred (mapping inc) as forgetting to pass args to (map inc) is often just a mistake in my code

slipset 2020-10-29T20:10:55.496900Z

@borkdude just got my emacs to talk to clj-kondo. Lovin’ it!

borkdude 2020-10-29T20:17:35.497200Z

❤️

slipset 2020-10-29T20:30:14.002900Z

Here’s a couple of linters I’d like (but they’d certainly be controversial): 1. Prefer partial over #(..) when all you’r doing is binding variables 2. Prefer named (fn foo […] …) over #(…) and certainly over (fn […]…) 3. Flag #(..) or (fn foo […] …) spanning multiple forms/lines

slipset 2020-10-29T20:32:16.004800Z

I guess 1) is hard, since you have to analyze the #(..) to understand that you’re just “currying”. 2) would be simple enough, warn/error on #(...) or (fn [..] ..) 3) should probably be doable…

borkdude 2020-10-29T20:53:14.005600Z

I wouldn't know why one would prefer partial over #(..) or (fn [...]), seems a bit random to me + you will lose reloading for vars you bind over with partial

borkdude 2020-10-29T20:54:42.008200Z

3 seems a bit arbitrary to me. 2. could implement, but not sure anyone would adopt this as a linter and adhere to it strictly in their code base. As an example, I recently implemented the shadowed-var linter. In theory very useful, but after using it a bunch, I found it too restrictive myself

slipset 2020-10-29T20:54:51.008400Z

It might be a principle somewhere around it, but it’s basically that when I see partial I know that there is nothing more going on than the binding of variables. If I see #(..) I have to read the form to se e that nothing else is going on.

slipset 2020-10-29T20:55:15.008900Z

I’m not at all asking you to implement, but it might be fun for me to try to implement at some point.

slipset 2020-10-29T20:55:58.009700Z

And I could deffo see that those are not linters that everybody would use.

borkdude 2020-10-29T20:56:43.011100Z

implementing is one thing, maintaining is another one. if something is wrong with a linter, usually I'm the one ending up fixing it, even if some other person wrote it (unfortunately). my point was more like: what's the point of implementing a linter and maintaining it indefinitely if it's too strict for anyone to use

slipset 2020-10-29T20:57:04.011600Z

As for 3) we have examples in our codebase of

(reduce (fn [acc x] 
 ;; 300 lines of code
  ) {} lol)

slipset 2020-10-29T20:57:26.012300Z

Hmm, didn’t consider the maintenance part, and that’s a fair point.

borkdude 2020-10-29T20:57:27.012400Z

ah good example, I get the point

slipset 2020-10-29T20:58:11.012800Z

Someone asked for “linter plugins” in Eastwood at some point.

borkdude 2020-10-29T20:58:44.013300Z

clj-kondo has this, it's called hooks. you can use it today. docs: https://github.com/borkdude/clj-kondo/blob/master/doc/hooks.md examples: https://github.com/clj-kondo/config

slipset 2020-10-29T20:59:24.014300Z

Right, so I can basically figure out how to write my own linter, stick it in a hook and voila presto?

borkdude 2020-10-29T20:59:38.014600Z

hopefully, yes

borkdude 2020-10-29T21:00:07.015300Z

what you can do with a hook is transform the shape of a call and do some linting on the original shape of the call

borkdude 2020-10-29T21:00:13.015600Z

so it's a kind of macroexpansion

borkdude 2020-10-29T21:00:26.016100Z

but then using clj-kondo / rewrite-clj node primitives

slipset 2020-10-29T21:01:03.016800Z

The thing with partial is somewhat related a thing I first heard on the Idealcast with Gene Kim and Michael Nygaard. Then I heard it again on an episode of the Corecursive podcast.

slipset 2020-10-29T21:01:48.017700Z

The thing in the podcasts was something like “The more abstract the types of the parameters of the function, the less the function can do”

slipset 2020-10-29T21:03:11.019200Z

So if you have a fn signature fn T t => T (sorry about the syntax) where T is some type, then this fn can only do one thing.

borkdude 2020-10-29T21:03:41.020Z

in Haskell yes, in Clojure we don't have this

slipset 2020-10-29T21:03:48.020200Z

if you have a fn signature fn Int i => Int you have a function that can do an infinite amount of things

slipset 2020-10-29T21:05:05.021700Z

So if you have (map (partial ...) foos) you know that you’re only binding parameters, whereas if you have (map #(….) foos) anything can happen.

borkdude 2020-10-29T21:07:43.022600Z

I don't really see the improvement. (partial foobar 3) or #(foobar 3 %) convey the same information and don't guarantee anything about potential side effects

borkdude 2020-10-29T21:08:42.024100Z

partial returns a closure. e.g. (partial foobar x) will capture x at one point in time. any changes to x won't be seen in that closure. which prohibits REPL-driven development.

slipset 2020-10-29T21:09:06.024500Z

My point is that the moment I see partial I can almost ignore the rest, but I have to read #(…) to the end to see that there is nothing else going on.

borkdude 2020-10-29T21:09:14.024700Z

https://twitter.com/borkdude/status/796018276044247041

slipset 2020-10-29T21:10:18.025Z

Right, didn’t consider that one.

2020-10-29T21:11:30.026200Z

I didn't know about not seeing the redef of foo

borkdude 2020-10-29T21:11:33.026400Z

I'm not saying: always use this or that, but a linter will say that and this is where I see not many people using it in the long run

2020-10-29T21:11:36.026600Z

that is a sneaky gotcha

slipset 2020-10-29T21:11:47.026800Z

I tend to do C-c C-k in emacs which solves the redef of foo

2020-10-29T21:12:04.027300Z

I do that too (so hopefully that works)

borkdude 2020-10-29T21:12:15.027900Z

not if foo is from another namespace, unless you're into the entire REPL reloaded workflow

✅ 2
2020-10-29T21:12:30.028200Z

I only really do C-x C-e when I'm doing stuff in rich comment blocks

2020-10-29T21:12:39.028600Z

anyway, good night all 😉

slipset 2020-10-29T21:13:07.029Z

Is the grownup telling us to go to bed?

slipset 2020-10-29T21:13:24.029200Z

Sounds like good advice.

raymcdermott 2020-10-29T21:57:11.029600Z

Good night

dominicm 2020-10-29T22:29:35.030600Z

I don't like partial because it obscures the arguments expected by the new function you've created. I've ended up in a muddle because of that many times.

👍 3
1
2020-10-30T08:46:59.033500Z

when you choose partial you are signalling that you expect at least two different arities, and that is a feature, seems to me