Fork me on GitHub
#clojure-uk
<
2017-03-02
>
practicalli-johnny02:03:19

@yogidevbear ClojureX bytes events are talk nights just like the monthly ones, but with a speaker associated with ClojureX (e.g have spoken at the conference previously)

yogidevbear07:03:58

Morning Cool, thanks John

jasonbell07:03:06

morning you crazy clojure cats

yogidevbear07:03:29

Jade! Wazzuuuuup

yogidevbear07:03:51

Just joking, I'll stop doing that Jase

jasonbell07:03:18

Itā€™s okay, I use it as leverage to give @agile_geek a really hard time šŸ™‚

yogidevbear07:03:43

Haha, and to convince him to do talks at events, yes?

jasonbell07:03:06

No no, I put proposals in. Only fair.

yogidevbear07:03:42

Proposals from agile_geek?

yogidevbear07:03:44

A different style of volunteering

jasonbell07:03:55

Iā€™m currently thinking of what to talk about this year....

dominicm08:03:03

I really need to come up with a good talk :)

Rachel Westmacott08:03:53

Good Morning! (And death to history!)

agile_geek08:03:31

@jasonbell you insulting yourself doesn't give me a hard time.. you're just perpetuating the meme I started...this makes me smile simple_smile

agile_geek08:03:02

Not sure you understand how schoolyard humour works?

agile_geek08:03:02

If you're trying to deflect by joining in the joke, that's cool but wouldn't cause me a hard time.

agile_geek08:03:29

Re: talk proposals from me...up until now I haven't had anything worth saying that's Clojure specific. I can talk about development processes/culture and architecture (generically) till the cows come home but none of it is anything to do with Clojure.

thomas08:03:47

@agile_geek the Clojure community is one things that makes Clojure such a joy to use...

thomas08:03:22

when I get stuck (which is quite often) I can come here (or other places) and ask my silly questions and you wonderful people help me (for which I am very thankful)

thomas08:03:17

so maybe a talk about how the the Clj community can even become better at this would be something you could talk about.

thomas08:03:23

just an idea....

otfrom09:03:10

I'm pretty sure agile_geek should propose his architecture experience report for this year

agile_geek10:03:40

It's a pretty incoherent story atm but I may submit if I can edit it into something useful

agile_geek10:03:55

It's nothing revolutionary BTW just personal realisations and quite satisfying resolutions to a number of problems I've wrestled with for years.

yogidevbear10:03:33

@agile_geek, you've got 9 months to put something together for ClojureX šŸ˜‰ Plenty of time to make it more coherent. And any "battle tested in the wild" tales would be helpful to devs of all ages and experience levels

agile_geek10:03:28

Less time than that for me to determine if it's worth submitting tho.

agile_geek10:03:30

and as this has so far been 8 months in the making and I've barely managed to write any of it down that doesn't bode well!

glenjamin10:03:40

my talks are usually months of thinking followed by a day or two of writing it down

yogidevbear10:03:32

I'm thinking about submitting a basic talk on Clojure to a ColdFusion conference in late October as there is some interest in Clojure within the cfml community thanks to Sean Corfield. Not sure if the talk would be any good though with me being a CLJ novice, but would give me something to work towards which would help me learn faster. Does that sound like a very silly idea?

thomas10:03:33

@yogidevbear not a silly idea at all... how about making it a very introductory talk.. this is how you get started... and then give a few examples of what the advantages are over cfml.

jasonbell11:03:41

@agile_geek - Last time I stood on a playground was in 1988, I assume you're still there šŸ˜‰

agile_geek11:03:47

@jasonbell absolutely...although I'm frozen in the playground of a few years earlier

yogidevbear11:03:24

@thomas, yeah, I was thinking along the lines of a talk called "Clojure, a whirlwind tour" and going over things like the resources/tooling (http://Clojars.org, Leiningen, Boot, etc.), language basics, code/file structure, ns, and maybe do a basic demo of a web app using ring, compojure, etc.

thomas11:03:52

@yogidevbear try and keep it simple.... I don't think there is a need to mention both lein and boot (just one would be fine) and I probably wouldn't mention clojars (unless someone asks).

yogidevbear11:03:15

Yeah maybe you're right. I thought discussing the tooling / resources might be useful to some though. Maybe it's more of a two talks type offering. One to go over the tooling/ecosystem and one to actually demo the language itself. That said, this will be the first time putting myself into a public speak situation so best not to bite off more than I can chew šŸ™‚

yogidevbear11:03:49

I know there is definite interest within that community so anything presented well would be welcome I think

agile_geek11:03:30

@yogidevbear You need to pick out 1-3 things you want to focus on for a 25 min talk or 1 thing for a 10 min lightning talk. Anymore than that and your message gets lost and you won't have time. These talks work best when given from a 'What worked for me" or "What I learned" perspective. Your suggested topics target beginners so I would focus on what you think you wissh you'd known when you started.

yogidevbear11:03:31

It sounds more and more like I'm actually going to put a proposal together for that conference šŸ˜±

yogidevbear11:03:16

What format do you guys normally use when submitting a talk proposal doc?

otfrom11:03:44

yogidevbear usually there is an online form to fill in. Short but punchy descriptions help

agile_geek11:03:10

@yogidevbear don't think we've formally opened CfP's yet

yogidevbear11:03:53

Oh, wasn't meaning ClojureX specifically

agile_geek11:03:15

Almost all conferences have some online submission form

mariusz_jachimowicz12:03:18

@yogidevbear please add to your presentation a picture where there are all languages as an bicycles with square wheels and Clojure one with circle wheels šŸ˜„

yogidevbear13:03:36

TBH, some languages are probably worst than bicycles with square wheels

thomas13:03:45

I would try and demonstrate how clojure is different and why that (most of the time, but not always) has advantages.

yogidevbear13:03:02

Well for one, it's FP vs OOP / procedural

yogidevbear13:03:13

But I take you're point

thomas13:03:52

what I have done in the past is show the various data structures (list, vectors, maps and maybe sets) and then map, filter and reduce.

thomas13:03:03

just fire up a repl and show them

yogidevbear13:03:15

I was thinking about demoing basic types and then lists, vectors, maps and sets and paralleling those to the data structures termed in cfml (structs, arrays, etc.)

rickmoynihan16:03:32

@dominicm: not followed all of your conversation about j.n.URI but be very wary of that class (and also j.n.URL which is a travesty). j.n.URI canā€™t encode/decode URIā€™s properlyā€¦ especially in double encoding scenarios,in particular where a query param key/value is an encoded URI itselfā€¦ e.g. if you URLEncode a uri that has a + in it in a qparam it will fail.

rickmoynihan16:03:51

j.n.URL should be avoided like the plague too - because its .equals method actually tries to resolve the URL!!! So never ever put that in a HashMap!

otfrom16:03:24

rickmoynihan what do you use for UR(L|I)s?

rickmoynihan16:03:49

otfrom: good question. I have a side project where Iā€™m writing a parser from the BNF spec (using instaparse & validating the model it with clojure.spec generators etc..) though thatā€™s quite a way off being finished. there are URI classes in RDF4j that we use; but they do very little validation; so we use them when we donā€™t care about validationā€¦ when we do, well we use java.net.URI with some horrible workarounds via grafter.url ā€” which provides a protocol abstraction over j.n.URI/L, itā€™s own record based one and the RFF4j implementations.

rickmoynihan16:03:33

grafter-url currently acts as our interface to stuff

rickmoynihan16:03:05

though there are some bugs in it too ā€” which is one reason why I want to fix it with a proper parser etc

otfrom16:03:34

sounds like a tough one and given your RDF work I'm guessing a real pain for you

rickmoynihan16:03:18

basically it turns out nobody parses URIā€™s properly (anywhere)

rickmoynihan16:03:49

(hereā€™s the horrendous bodge around double encoding with j.n.URI: https://github.com/Swirrl/grafter-url/blob/master/src/grafter/url.clj#L123 )

rickmoynihan16:03:00

but it works properly

rickmoynihan16:03:33

basically you have to use reflection to forcibly set a private field

rickmoynihan16:03:51

so you can fix the behaviour of the constructor

rickmoynihan16:03:22

and handle encoding/decoding yourself

rickmoynihan16:03:07

even more šŸ˜± is that no web browser parses URLā€™s properly either: https://webkit.org/blog/7086/url-parsing-in-webkit/

rickmoynihan16:03:19

in practice itā€™s not a huge problem for our RDF workā€¦ usually you can just treat URIā€™s as opaque identifiers, and normally we want them to be pretty clean for readability purposesā€¦ the bodge was necessary because a + was used in a URI which a webservice then encoded on a qparam, and it caused j.n.URI to freak out.

dominicm17:03:35

@rickmoynihan I'd be very interested to know if the library I linked could handle it at all

rickmoynihan17:03:19

@dominicm: if they do thatā€™d be great - itā€™d save me some work šŸ™‚

rickmoynihan17:03:44

Iā€™m discouraged by the use of pretty crazy regexes though

rickmoynihan17:03:17

@dominicm: and also their rationale is mistaken

rickmoynihan17:03:35

equality check on URI is fineā€¦ equality check on URL does the DNS lookup

dominicm17:03:36

@rickmoynihan Me too, which prompted a discussion on parsing. I get the impression that the regexes are born out of knowledge of RFC

rickmoynihan17:03:58

If Iā€™m nitpicking I also disagree a little with their modelā€¦ I think the model should ideally represent paths and query fragments as vectors of strings not strings themselves

dominicm17:03:49

@rickmoynihan paths should be strings, not vectors of strings, no?

dominicm17:03:58

Or is separation part of the RFC?

rickmoynihan17:03:43

well a common operation is to modify path segments etcā€¦ to .e.g. canonicalise etc

rickmoynihan17:03:26

Iā€™d probably represent a path of /// as something like [ā€ā€ ā€œā€ ā€œā€]

rickmoynihan17:03:56

but maybe strings are better

dominicm18:03:43

@rickmoynihan I agree it's common to treat it as segments, but I'd rather leave that task up to bidi šŸ˜‰

dominicm18:03:37

I would like to have query fragments as a map though. Much like cemerick.URI

rickmoynihan22:03:13

dominicm: the thing is query fragments arenā€™t always a map. In grafter-url we provide two ways to view them, as ordered pairs or as a map.

dominicm07:03:24

@rickmoynihan in that case the value becomes a vector doesn't it. Hadn't considered that ordering of all params might be useful

rickmoynihan09:03:15

Technically no, because the ordering of qparams in a URI can be meaningful. Sure, it seldom is meaningful, because the hash-like semantics are so common place; but the RFC considers the whole of a URI to be an identifier so preserving order is important.

dominicm14:03:00

Interesting, didn't know that property of URIs, I'll have to bare that further in mind in the future. I was aware of the repeated presence of a qparam having meaning, but not the ordering.

dominicm18:03:06

@rickmoynihan https://github.com/weavejester/integrant/issues/12 I went to open this exact issue last night šŸ˜†

rickmoynihan22:03:23

dominicm: lol Iā€™ve been meaning to open that issue for a while - only got round to it yesterday though.

dominicm18:03:35

On one of our client projects we're basically doing "component on top of aero" so it might make sense for us to swtich to integrant

weavejester18:03:41

Coincidentally, Component on top of Aero was one of the things I tried in Duct before moving to Integrant.

dominicm19:03:42

@weavejester Interesting, any strong reason you'd encourage a switch?

weavejester19:03:19

@dominicm I can only speak about my own reasons, but one of the problems I had with a Aero/config to Component approach is that anything I wanted to configure and happened to be tied into the dependency graph, I needed to wrap in a component.

dominicm19:03:45

@weavejester I don't understand that, can you rephrase please?

weavejester19:03:16

Sure. So for instance, say I had some Ring middleware that needed to access the database.

weavejester19:03:41

I canā€™t include that into a component dependency graph without writing a function that converts a component into a Ring middleware function.

weavejester19:03:40

I had the same problem with handlers, but eventually I just found that I was writing components for too much. They were too heavy to support the granular configuration I wanted.

weavejester19:03:14

Integrant can effectively extend further, because itā€™s not as heavy. It doesnā€™t need to wrap everything in components, because the dependency graph is declared in the configuration.

dominicm19:03:01

Ah, I understand. Yes, sorry, I see what you mean now. That's a general issue with Component as opposed to an aero/component combination problem though, yes?

weavejester19:03:45

Yeah, but if you donā€™t want to connect Component to a configuration then you can just do things with functions.

weavejester19:03:03

Like you can just hard code stuff and have a minimal top-level config

weavejester19:03:20

But if you want to configure everything, if you want your application structured around data

weavejester19:03:29

Then Component gets a bit heavy.

jasonbell20:03:22

In regards to RDF @rickmoynihan @otfrom is there anything worth interoping from the old Jena Java API for RDF? It's years old but it was the best thing at the time for parsing RDF for the JVM.

rickmoynihan22:03:24

jasonbell: suggest we take this to #rdf ā€” Iā€™m more of a fan of RDF4j (formerly sesame) than Jena - as the APIā€™s are much much cleaner and nicer. Grafter wraps it in a clojure layer: https://github.com/Swirrl/grafter I have a plan to eventually port grafter to a core.rdf project and interop with either sesame/jena backends too.

rickmoynihan09:03:05

We use both JENA and sesame/RDF4j ā€” as JENA is better for some things and RD4j for others. Code quality / readability / usability in RDF4j is much higher IMHO though. (disclaimer Iā€™m technically an RDF4j committer - but more in name not in practice, and my opinions were formed before I was invited to be one)

rickmoynihan09:03:49

For reading/writing RDF RDF4j/sesame has a pretty nice/clean API and supports basically every RDF serialisation reliably & grafter exposes that capability as pretty idiomatic clojure lazy sequences. The usage of this bit is largely undocumented but straightforward, stable and widely used at swirrl.

dominicm20:03:15

@weavejester we use #ref to bring in configuration like that, or am I misunderstanding? (I'm running a bit slow tonight)

weavejester20:03:10

@dominicm #ref as in Aeroā€™s #ref, rather than Integrantā€™s #ref?

dominicm20:03:27

@weavejester yes, aero's, my apologies.

weavejester20:03:16

So if you think of it as being divided into ā€œconfigurationā€ and ā€œimplementationā€. So a configuration might be a database URI, and an implementation might be a database connection.

weavejester20:03:46

Some implementations depend on other implementations.

weavejester20:03:04

Aero allows you to #ref other parts of the configuration

weavejester20:03:12

But not the implementation.

weavejester20:03:03

For instance, a middleware function might need a datomic database connection. So the middleware configuration depends on the database implementation.

weavejester20:03:23

Does that make sense at all, @dominicm? šŸ™‚

dominicm20:03:16

@weavejester ah, so #ig/ref is superior to #aero/ref because it can auto-"componentize" anything that it needs to, to a degree.

weavejester20:03:36

Not sure Iā€™d say itā€™s superior šŸ™‚

weavejester20:03:58

But it does do more. It brings in the ā€œimplementationā€ rather than the ā€œconfigurationā€.

dominicm20:03:42

Just thinking about a feature for aero where a "ref" could be resolved in different ways. Unsure about quite how it would work though. Probably don't want to restart your system each time you re-read the config

weavejester20:03:25

I think you do want to restart your system each time you change the configuration. But you can scavenge connections etc. from the old system.

dominicm20:03:05

@weavejester I mean more that. Reading the config shouldn't cause the system to be read.

dominicm20:03:28

Aero operates at config read time, for the most part.

weavejester20:03:22

Right. But youā€™d ideally have something like: (run-system (read-config ā€œfoo.ednā€)) => system

weavejester20:03:44

You produce a system from a configuration. When youā€™re done with the system, you discard it.

dominicm20:03:56

Yeah, exactly.

dominicm20:03:10

The problem is that aero's current config depends on copying.

dominicm20:03:28

That perhaps isn't a problem actuallyā€¦ I need to think

dominicm21:03:33

@weavejester approximately how does #ig/ref work? Does it attach metadata / replace with a particular container that integrant knows?

weavejester21:03:20

@dominicm No, it doesnā€™t use any containers. When you init an integrant configuration map, the keys are walked in dependency order, producing an implementation map. Refs are replaced with the corresponding implementation.

weavejester21:03:05

Because the dependency tree is static, and can be worked out from the configuration, we can build it up without using any sort of container or metadata system.

weavejester21:03:48

That said, in order to halt the tree, the original config map is attached as metadata to the implementation.

dominicm21:03:54

@weavejester I wonder if that would have worked for aero actually šŸ˜Š

dominicm21:03:24

I built a topological sort on top of the refs.

dominicm21:03:31

@weavejester do you handle dependency cyles?

weavejester21:03:03

Iā€™m using Stuartā€™s dependency library, the same one thatā€™s used for Component. Any dependency cycles cause an error.

dominicm21:03:50

@weavejester okay, same as aero then. Okay, I thought you were doing a (start) over the args, not building a dep graph

dominicm21:03:59

I suppose you can't do that anyway right

weavejester21:03:48

Yeah, it builds up a dependency graph to figure out which keys to init first.

dominicm21:03:57

I think I need to play with it a bit. I've got a little toy project currently on mount, so a switch would probably be a good experiment.

weavejester22:03:58

@dominicm Oh, you meant the container of the ref itself. Yeah, itā€™s just a record with a single key.

otfrom22:03:55

weavejester I didn't know about that Stu Sierra dependency lib.

rickmoynihan23:03:09

@dominicm @weavejester: Iā€™m very curious to try integrant (which I think looks like a nice improvement on component ā€” and seems significantly better than mount)

rickmoynihan23:03:26

in particular Iā€™d also like to hear about how well it works with aero

weavejester23:03:21

@rickmoynihan You should just be able to use it straight with Aero, once you add a data reader for integrant.core/ref.