clojure-uk

A place for people in the UK, near the UK, visiting the UK, planning to visit the UK or just vaguely interested to randomly chat about things (often vi and emacs, occasionally clojure). More general the #ldnclj
jiriknesl 2021-01-14T06:24:52.000200Z

Good morning

2
djm 2021-01-14T06:45:56.000600Z

πŸ‘‹

djm 2021-01-14T06:47:14.000700Z

We've not had the best of experiences with java/spring boot for creating graphql apis. Are things better in clojure land?

dharrigan 2021-01-14T06:49:43.001100Z

Hey Everyone! πŸ™‚

dharrigan 2021-01-14T06:50:54.001200Z

Oh, my comment may be misleading. Backend is just REST, it's the frontend, that is React and Apollo. I have heard a few good things about <https://lacinia.readthedocs.io/en/latest/> however.

dharrigan 2021-01-14T06:51:58.001400Z

I was expressing how easy it was to change the javascript, have it hot reloaded and at the same time also eval my clojure buffers (a much better experience as we know) without having to stop/recompile/start again πŸ™‚

dharrigan 2021-01-14T06:54:55.001600Z

Since on the other backend I look after, all done in Kotlin, I've got this library <https://github.com/ExpediaGroup/graphql-kotlin> down to explore, which also works with Spring(boot)

dharrigan 2021-01-14T06:55:25.001800Z

Do you use that library?

dharrigan 2021-01-14T06:55:33.002Z

(or, the graphql-java version)

djm 2021-01-14T06:58:46.002200Z

We did one thing using the graphql-java spring boot starter, and that's basically fine, but doesn't support batch loading (a fix for that was merged well over a year ago, but they haven't done a release since, because there's a serious problem with it).

djm 2021-01-14T07:00:04.002400Z

Then for another project we tried to use the grahql kickstart library instead (which is built on top of graphql-java), but we had to abandon it, because it was taking several seconds to construct the json response

djm 2021-01-14T07:00:44.002600Z

I'm guessing that the expedia one is this best choice

djm 2021-01-14T07:02:15.002800Z

Kotlin is a bit of a sensitive subject, because at some point our architect (and others) were keen on doing things with Kotlin, so I was pushing for it, but then he backtracked on that because he decided we had too many (new) technologies being used. (We do have some tests written in Kotlin, though!)

dharrigan 2021-01-14T07:48:08.003Z

It's ironic, but when I joined my current company, I was the one who introduced Kotlin. We abandoned writing Java +3 years ago. Everything is written now in Kotlin or Clojure (which I advocated too).

dharrigan 2021-01-14T07:48:23.003200Z

Everyone at work is very very happy with Kotlin (and I'm very very happy with Clojure)

dharrigan 2021-01-14T07:49:19.003400Z

I do still write Kotlin too, for other projects I look after.

mccraigmccraig 2021-01-14T07:50:10.003800Z

mΓ₯nΒ‘ng

dharrigan 2021-01-14T07:50:43.003900Z

I don't think anyone at our work would like to go back to writing vanilla Java again. We don't disallow it, we don't discourage it, but we don't promote it either πŸ™‚

dharrigan 2021-01-14T07:51:08.004200Z

It's an option - a few "blessed" languages on the JVM - Java, Kotlin, Clojure.

dharrigan 2021-01-14T07:51:29.004400Z

Pick your poison! πŸ™‚

djm 2021-01-14T07:51:49.004600Z

We have a few people who are keen on Kotlin

djm 2021-01-14T07:52:29.004800Z

I think at least one person who looked at it and said "That's different, I don't like it"

djm 2021-01-14T07:53:00.005Z

And some who seem interested to learn it, but haven't

alexlynham 2021-01-14T08:21:27.005200Z

morning

alexlynham 2021-01-14T08:23:57.005300Z

i seem to have implemented clojure's case and cond forms, complete with square bracket list syntax in my current TS project lol

alexlynham 2021-01-14T08:24:53.005400Z

the typescript switch bulls--t was so verbose for what we needed (predicate matching for querystrings) so started writing a data oriented thing and then eventually realised it was just a mini lisp DSL

alexlynham 2021-01-14T08:25:12.005500Z

except lazy like haskell, thunks everywhere carrying around little happy monads

alexlynham 2021-01-14T08:25:33.005600Z

like Bob Ross' little happy trees

dharrigan 2021-01-14T08:48:02.006Z

No mistakes, just happy little accidents.

dharrigan 2021-01-14T08:48:12.006200Z

He's great Bob

thomas 2021-01-14T09:02:15.006400Z

morning

2021-01-14T09:10:30.006600Z

Morn'

2021-01-14T10:25:33.007400Z

Morning

jasonbell 2021-01-14T13:04:09.007800Z

Morning

alexlynham 2021-01-14T13:16:33.007900Z

@arohner whenever i see your handle, my brain somehow reads it as the title of this perfect circle song (renholdΓ«r) https://youtu.be/KayJYjg1vbI

πŸ˜‚ 1
dharrigan 2021-01-14T15:08:22.008400Z

dharrigan 2021-01-14T15:08:23.008800Z

Coffee time!

πŸ‘ 2
dharrigan 2021-01-14T16:28:59.011Z

Here's a question. You know in architecture, you would traditionally have a 3-tier layer, i.e., Presentation/API, Service/Application, Repository/Data, would there be a similar setup in Clojure, i.e., an API layer, then an intermediate layer that may do some data translations before hitting the data layer? What do people do in Clojureland?

dharrigan 2021-01-14T16:29:24.011300Z

bbiab.

alexlynham 2021-01-14T16:30:30.011400Z

i quite like vertical slices where each vertical slice has a transformations namespace and a db namespace so similar to what you're describing

πŸ‘ 1
dharrigan 2021-01-14T16:38:20.012700Z

would you call that foo.bar.transformations?

alexlynham 2021-01-14T16:42:17.012900Z

probably yers

alexlynham 2021-01-14T16:42:57.013Z

db.clj transformations.clj utils.clj format.clj are very common namespaces in my subfolders lol

alexlynham 2021-01-14T16:44:31.013200Z

in current typescript project very similar too (typed functional typescript) db.ts transformations.ts schemas.ts types.ts

alexlynham 2021-01-14T16:45:16.013300Z

and then the api layer is all in a totally separate folder - oriented into REST entity subfolders with stuff grouped into files there

dharrigan 2021-01-14T17:07:42.013500Z

ha, like me!

dharrigan 2021-01-14T17:07:53.013800Z

except for the transformations thingie πŸ™‚

alexlynham 2021-01-14T17:11:26.013900Z

i tend to try and get any data -> data functions for a given entity away from the side effecting ones if possible cos you very quickly see then what the general case is & then can lift them up and out to more general helper namespaces or whatever

alexlynham 2021-01-14T17:11:39.014Z

in our current project that's led us to a monadic approach

alexlynham 2021-01-14T17:12:35.014100Z

cos generalising the transformation functions leads you to pipelines of composed monads which you can then safely chain in your side effecting functions (i.e. the outer handlers -> equivalent to the main fn essentially)

dharrigan 2021-01-14T17:13:43.014400Z

😷

mccraigmccraig 2021-01-14T17:14:29.015Z

i wouldn't worry @dharrigan - i think R is far below 1 for this particular pathogen

alexlynham 2021-01-14T17:14:31.015100Z

it's really noticeable how the railway style we are using Eithers how composable they become

alexlynham 2021-01-14T17:14:47.015200Z

the general case for a problem becomes ludicrously general

alexlynham 2021-01-14T17:15:23.015300Z

hence why i was essentially reimplementing clojure's case and cond yesterday so we could chain thunks of compatible monads

alexlynham 2021-01-14T17:15:39.015400Z

just partial application innit :D

alexlynham 2021-01-14T17:16:00.015500Z

or, at least, just syntactic sugar for what we could accomplish with partial application :)

mccraigmccraig 2021-01-14T17:18:17.016700Z

yeah, i've been working on my monad lib a bit recently and it's really interesting how some very generic concepts are emerging, which can be uniformly applied across very different types of contexts

alexlynham 2021-01-14T17:18:43.017100Z

i'm definitely beginning to see how combinators become increasingly useful

alexlynham 2021-01-14T17:19:48.017800Z

cos the general case of a cond where the dispatch of each pair is a thunk is that the predicate should be a thunk too, which is a combinator i think... it's thoughts like these that reveal some of this stuff is above my brainpower level lol

mccraigmccraig 2021-01-14T17:22:38.018800Z

yeah, general cond sounds like a list of [pred-thunk match-thunk] pairs

alexlynham 2021-01-15T09:10:34.026500Z

xactly, but then you go "is this too general to be useful"

alexlynham 2021-01-15T09:10:59.026700Z

i mean the answer is no, but it's like an alien language to anybody that's not done much fp i guess

alexlynham 2021-01-15T09:11:21.026900Z

becoming increasingly aware of the fact this code base is going to need handing over in 3 mths or so

mccraigmccraig 2021-01-15T09:13:44.027200Z

it's the abstraction dilemma - do you build new abstractions to make more robust software re-using fewer, more fundamental, better tested, components, or do you use familiar generic components more verbosely and repetitively because new developers will find it easier to grok ?

alexlynham 2021-01-15T10:24:09.027800Z

see also: monads

alexlynham 2021-01-15T10:24:15.028Z

see also: fp in general

alexlynham 2021-01-15T10:24:16.028200Z

haha

alexlynham 2021-01-15T10:24:19.028400Z

but yeah exactly

alexlynham 2021-01-15T10:25:08.028600Z

i suppose it's a different tradeoff calculation when you're a contractor who knows you've gotta hand over software on paper - but in reality all developers come and go on a project so maybe it's more about pragmatism in the face of that

alexlynham 2021-01-15T10:25:46.028800Z

what would you do if onboarding wasn't an issue / what is the most robust general case solution sui generis

mccraigmccraig 2021-01-15T11:15:52.030500Z

i'll probably always favour a better abstraction 😬, although i've not gotten around to rewriting everything in haskell yet, so maybe not

alexlynham 2021-01-15T12:07:23.035200Z

lol

dharrigan 2021-01-14T20:48:13.022100Z

If I'm playing around at the repl, can I "inject" a var in #'user to another namespace, i.e., #'user/foo injected into my.namespace/foo so that if I was to then do my.namespace/foo it would be the same as the value of #'user/foo?

dharrigan 2021-01-14T20:48:47.022500Z

inject is probably a bad word, but I hope I convey what I mean

seancorfield 2021-01-14T20:54:30.022800Z

intern

seancorfield 2021-01-14T20:55:08.023700Z

(intern (find-ns 'my.namespace) 'foo foo) will stick foo in my.namespace with the current value of foo from the current ns.

seancorfield 2021-01-14T20:55:59.023900Z

dev=&gt; (ns foo.bar)
nil
foo.bar=&gt; (in-ns 'dev)
#object[clojure.lang.Namespace 0x7bdf8c92 "dev"]
dev=&gt; (defn foo [x] (* x x ))
#'dev/foo
dev=&gt; (intern (find-ns 'foo.bar) 'quux foo)
#'foo.bar/quux
dev=&gt; (in-ns 'foo.bar)
#object[clojure.lang.Namespace 0x2bfa5678 "foo.bar"]
foo.bar=&gt; (quux 12)
144
foo.bar=&gt; 
@dharrigan

seancorfield 2021-01-14T20:56:10.024200Z

I don't know if that's the best way but...

dharrigan 2021-01-14T20:59:35.024400Z

perfecto

dharrigan 2021-01-14T20:59:42.024600Z

it's only for playing around πŸ™‚

dharrigan 2021-01-14T21:00:02.024800Z

thanks

dharrigan 2021-01-14T21:01:34.025Z

works a treat