Fork me on GitHub
#clojure-uk
<
2018-05-23
>
alexlynham08:05:50

morrrrrrning

otfrom08:05:01

ni hao (sorry about the lack of tone marks)

rhinocratic09:05:21

Ma nah ma nah.

😄 8
yogidevbear09:05:29

G'day beautiful people

👋 4
mccraigmccraig09:05:16

you should probably only write clojure in peace @agile_geek

👍 4
8
agile_geek09:05:05

I usually end up in pieces when writing it…does that count?

mccraigmccraig09:05:16

yeah, homophones always count

peterwestmacott09:05:52

I heard that “clojure” is homophonic…

😂 4
danm09:05:18

Ello ello

mccraigmccraig09:05:20

have you considered sxml and specter as a clojure alternative to xpath @lady3janepl ? i haven't done much xml stuff in clojure, but in a previous life https://github.com/mccraigmccraig/rsxml worked out well for me

3Jane09:05:51

I… kinda wrote something similar out of desperation, funny how Lisp syntax sticks with you once you get used to it XD (I’m still “in a previous life”)

guy09:05:09

morning!

👋 4
3Jane09:05:55

and from xpath (or a similar tool) I needed a good DSL to begin with, since the data is richer than xml and I wanted to define search patterns for declarative configuration. I’m going to eventually do a Clojure version (crosses fingers) and specter is definitely something I will integrate.

3Jane09:05:04

Thank you for pointing me to sxml 🙂

3Jane09:05:01

(…that is, if it will still make sense to compete with lacinia.)

guy09:05:50

ah neat how are u finding lacinia/graphql? I’ve used it a little and found it to be quite nice

3Jane13:05:12

(ah sorry missed the thread: I haven’t used it in depth yet since wrong language at the moment)

👍 4
danm09:05:33

Aah, you're doing graphQL stuff?

🎉 8
mccraigmccraig09:05:56

dunno - i would generally only use SXML for working with legacy XML data or SOAP apis... i haven't used graphql yet, but it looks pretty cool

danm09:05:39

I'd be interested if you get a nice write-interface through it. We quickly managed to write a really simple and good read API using graphQL, but we wanted the one API for all interactions and when we tried to build the write API it just because a cludgy mess

guy09:05:13

How many mutations did you have out of interest?

guy09:05:43

Also did you use / get working graphiql?

danm09:05:22

We did get graphiql working, although I can't recall if we had any issues doing so

guy09:05:57

ah ok cool. I had some error with input-objects and never had the time to look into why it didn’t work

danm10:05:44

In terms of mutations, the system in question has (It's a legacy DB, that we were looking to build a new API on the front of to replace the existing XML one) about 60 object types, with a given object's data being spread over anything from 1-5 or so tables (nested lists of sub-objects) and objects being able to be related to each other etc

danm10:05:36

The read API was really nice and Just Worked using the schema we defined for pretty much everything. We got up to the first 2 or 3 objects for the write API and it was already confusing, so we dropped the idea

guy10:05:48

ah, i can see why that would start turning into a big mess. I think for the javascript clients i’ve seen you can separate schemas for different aspects of the code base. But so far with my experience with lacinia we just ended up having one edn file. Did you have just one big one? or did you try splitting them up as well?

danm10:05:02

We just had one big one

guy10:05:31

ah yeah even more confusing

danm10:05:38

It wasn't the schema, so much as the code

guy10:05:46

oh really?

guy10:05:11

I found having separate resolvers to make it quite easy to separate and manage

guy10:05:21

but we only have like 10-12 mutations

guy10:05:33

So scale wise its much smaller than yours

guy10:05:06

>with a given object’s data being spread over anything from 1-5 or so tables I guess this is why it became super complicated?

danm10:05:26

With the read schema you could define all the lower level objects and define their relationships to build up the higher level objects, and that matched how clients wanted to read things and meant mostly the schema defined what they could query and how, with code only doing very basic lookups at the lowest level.

danm10:05:04

With the write schema we never managed to make it do the same thing. We were effectively implementing in code the same sort of logic that the schema gives you 'for free' on read.

👌 4
guy10:05:37

ok gotya i understand, thanks!

danm10:05:08

Plus of course on write you have questions like "If fields are optional, and a client doesn't provide it when updating an existing object, does that mean it should be nulled out, or just left with whatever the current value is?"

danm10:05:35

In XML it's easy, you have to provide all or nothing. But the whole point of graphql is you only ask for (and provide?) the bits you care about

danm10:05:13

But that was actually a smaller side issue

guy10:05:38

Yes i never figured that one out either

guy10:05:58

but for the type of data we used it always had to have some sort of value

guy10:05:49

well actually re-reading ur comment

guy10:05:02

if u wanted to update ur user object, we only updated the fields you sent

guy10:05:32

So you could effectively never blank out all your fields if that makes sense?

danm10:05:04

Oh yeah, but sometimes you want to blank a field. Like unsetting a parent/child relationship

danm10:05:26

And in the XML API you do that by just not providing the <parent> element, so clients kinda expect that

guy10:05:07

I think i would guess that the graphql way would be to have a separate mutation for removing that parent/child relationship

danm10:05:11

But in graphQL maybe you'd have to provide the key, but with value null? But then you have to know whether the key exists to unset

danm10:05:18

Possibly

danm10:05:52

But our objects are really quite complex. There might be 10-20 relationships like that per object type. We didn't really want to create separate mutations for all of them. The idea was to provide a simpler API than the XML

guy10:05:54

To me it “felt” like you are supposed to separate a lot of functionality into basic mutations which do maybe one or two things. That way you could start calling them one after another. Thats why i believe mutations are sequential. But i’ve had limited experience really.

guy10:05:11

Yeah exactly

guy10:05:21

I can totally understand your viewpoint haha

danm10:05:43

Yeah, you're probably right, and if the API was designed from the start as graphQL maybe that is how it would have been done

guy10:05:56

yes totally, i found that to be the case as well.

danm10:05:04

But for some things it's not valid to create those small mutations separately

👌 4
danm10:05:05

Like, some things may have to have a parent, so the base object creation should fail if one is not set. But in other things it's optional

guy10:05:09

I’m going to still investigate more about graphql i reckon. I’m going to look into the more popular js libraries to get a better understanding of what is possible. + reread the spec again. I really enjoyed developing with graphql/lacinia but am pretty much just self taught so its been a bit tricky

danm10:05:40

For read it was brilliant. I'd definitely consider it if we wanted to provide a read-only API to data

👆 4
guy10:05:20

Theres also interesting aspects like having an ID that works across mutations/queries so you can resolve in the object is the same across different calls and things. Like the actual graph aspect of it. I read about it one time but never really found out more 😭

alexlynham11:05:37

yeah my experience was similar in that I found read to be chefs_kiss.gif but write was a lot more involved

alexlynham11:05:59

was only a proof of concept hack anyway, but I wasn't sure if I'd have taken it further

alexlynham11:05:27

I like that it's giving you the query and the documentation though, so it's like a turbo-charged combo of both REST and OpenAPI/swagger

rhinocratic11:05:57

I'll be interested to see how schema stitching develops, and whether that will fit easily with Lacinia.

alexlynham13:05:28

yeah at least they use plumatic/schema, which in my experience is quicker to stitch together

danm09:05:53

Using lacinia

3Jane10:05:12

Yeah, graphql - not lacinia because I need to use PHP due to preexisting constraints

dominicm10:05:42

Time to build a clojurephp

😱 4
3Jane10:05:49

The other day I was trying to figure out truffle and graalvm for precisely this reason 😄 (integrating php bits into code primarily in something else)

3Jane10:05:28

but… yeah. Most implementations out there (not just in PHP) simply copy the reference implementation of graphql server and possibly also dataloader (for limited batching)

3Jane10:05:49

the reference implementation gives you a very restricted view of the context (which field you’re requesting, and what the immediate parent object is)

3Jane10:05:52

which is okay when you have a small, shallow schema with relatively few connections. We’ve got a really complicated one (as in, lots of types, and dense in some places) with multiple datasources so query batching is complicated and can depend on larger chunks of the graphql query 🙂

3Jane10:05:30

Have any of you guys had a chance to compare sangria (the scala lib) to lacinia?

korny12:05:17

I’ve done a lot of graphql querying - mostly in ruby though as it’s for $client. I quite like it, at least as a client trying to get info out of github!

korny12:05:46

Though I hate the ruby graphql library in one particular design decision they’ve made - they mandate that your graphql client is a static constant. :face_with_rolling_eyes:

korny12:05:59

oops, 👶 is waking, back to #dadops

👶 8
korny12:05:03

Aaand he went back to sleep. Back to fiddling with code 🙂

👍 4
guy12:05:11

Babys are cute 😄

korny12:05:21

Sigh - how do you refer to a nested static enum? <digs>

guy12:05:23

My youngest just learnt to climb things 😭

korny12:05:16

ah - DiffEntry$ChangeType/ADD

korny12:05:54

@guy yeah - Rowan is 17 months old, he’s climbing everything. It’s madness. He spent 20 minutes this morning climbing me, so he could get to the radio and fiddle with the controls.

korny12:05:03

And soooo cute. 🙂

guy12:05:14

Stuff like that makes it all worth it

korny12:05:07

Yeah. I’m currently working a 4 day week, so Wednesdays are my at-home-dad day - it’s awesome, I get a full day a week with him, well worth it.

guy12:05:41

damn i would love to be able to do that!

guy12:05:52

How did you negotiate that with your employer?

guy12:05:18

I’ve always been quite daunted about asking for a 4 day week 😞

korny12:05:55

I just asked 🙂 It helps that my wife works for the same company, and it was a combo of her going back to work, and me dropping down to 4 days.

guy12:05:13

ahhhh ok cool. Thats true, if you don’t ask you don’t get. OK i’ll be braver next time :thumbsup:

korny12:05:57

It also helps that I'm a consultant so not generally filling a full time role. But honestly, most full time jobs could be done in 4 days. I'm far more efficient 4 days a week than 5.

👍 8
3Jane13:05:02

My internship was half-time (because I was also full time uni student), after which I transferred to a 4 days-worth week, specifically because I asked

3Jane13:05:26

(also found myself more efficient this way, although I worked to 5 days, just shorter workdays)

3Jane13:05:10

what I also found was that it killed my career at that place, ie people from the same cohort got promotions and I didn’t because I was a part-timer.

3Jane13:05:45

so, ymmv but be careful about side-effects.

guy13:05:43

Yeah i’m thinking of working 4 days a week because of my kids really. I don’t mind a pause in career if i can have a better family Quality of life

3Jane13:05:21

If you’re male, it probably helps; at the same place I knew an older woman, a working mother who also transferred to not-full-time in order to have more time for her kids, and she got sidelined into non-contributing, busywork projects. (It’s possible they thought I was going the same route and my ask was an indication of me going off on parental leave soon.)

3Jane13:05:24

It’s all tradeoffs and dealing with people’s preconceptions.

guy13:05:17

Sure sure

agile_geek13:05:42

I’m waiting for my youngest to stop the whining phase….. 19 years and counting…might be onto a losing proposition!

😂 8
3Jane13:05:42

np 🙂 good luck with getting a good arrangement, time with family is extra valuable

3Jane13:05:37

Oh: also working at a place for some time before asking seemed to help (ime) with negotiating custom arrangements. I’ve done a period of remote work for a company that officially didn’t have remote work arrangements at the time. Perhaps managers want to see that you can function in normal conditions, and are happy to relax afterwards.

👍 4
korny13:05:48

Yeah - I've been at ThoughtWorks for 7 years so have a certain amount of good will there! Also as a company we are working hard to be more family friendly. It's tricky as so much consulting involves travel, but at least we are working on it.

👍 8
otfrom12:05:14

trying to reproduce periodic-seq in clojure.java-time

(take 3 (map #(t/plus (t/zoned-date-time (t/local-date-time 2017 7 1 0) (t/zone-id "UTC"))
                                   (t/months (* 1 %)))
                          (range)))
(#object[java.time.ZonedDateTime 0x1e217259 "2017-07-01T00:00Z[UTC]"] #object[java.time.ZonedDateTime 0x1202d6f "2017-08-01T00:00Z[UTC]"] #object[java.time.ZonedDateTime 0x624a7121 "2017-09-01T00:00Z[UTC]"])

otfrom12:05:21

is a bit hard coded atm, but thoughts?

otfrom12:05:46

(I just want a seq of YYYY-MM things that I can use)

otfrom12:05:36

that specific version is probably good enough for what I need atm. Was just wondering if someone had seen something more specific

peterwestmacott13:05:37

if you just want YYYY-MM, do you know that there’s a YearMonth class in java.time ?

peterwestmacott13:05:20

eg. (take 3 (iterate #(.plusMonths % 1) (YearMonth/parse "2018-05")))

otfrom13:05:44

I ended up with

(defn months-seq
  ([start]
   (map (fn [x] (t/plus (t/zoned-date-time start (t/zone-id "UTC"))
                        (t/months (* 1 x))))
        (range)))
  ([start end]
   (take-while #(t/before? % end)
               (months-seq start)))
  ([start end fmt]
   (map #(t/format fmt %) (months-seq start end))))

otfrom13:05:14

working with year-month is probably better

peterwestmacott13:05:27

I think there’s a wrapper in c.j-t

otfrom13:05:02

there is for some of it

otfrom13:05:22

struggling a bit to format the year-months back into strings

otfrom13:05:56

ok, yyyy-MM rather than YYYY-MM then

otfrom13:05:07

now it is:

(defn months-seq
  "Takes t/year-months like: (months-seq (t/year-month 2017 7) (t/year-month) \"yyyy-MM\")"
  ([start]
   (map (fn [x] (t/plus start
                        (t/months (* 1 x))))
        (range)))
  ([start end]
   (take-while #(t/before? % end)
               (months-seq start)))
  ([start end fmt]
   (map #(t/format fmt %) (months-seq start end))))

otfrom13:05:31

after I figured out I was specifying the format wrong (and it was looking for days of the week)

otfrom14:05:31

so that I can do a range of months starting with the start date (add 0 months)

otfrom14:05:44

changed it again as I want it to be inclusive of the end

(defn months-seq
  "Takes t/year-months like: (months-seq (t/year-month 2017 7) (t/year-month) \"yyyy-MM\")"
  ([start]
   (map (fn [x] (t/plus start
                        (t/months (* 1 x))))
        (range)))
  ([start end]
   (take-while #(t/before? % (t/plus end (t/months 1)))
               (months-seq start)))
  ([start end fmt]
   (map #(t/format fmt %) (months-seq start end))))

(comment
  (months-seq (t/year-month 2017 7) (t/year-month) (t/formatter "yyyy-MM"))
  ("2017-07" "2017-08" "2017-09" "2017-10" "2017-11" "2017-12" "2018-01" "2018-02" "2018-03" "2018-04" "2018-05"))

seancorfield15:05:50

I don't get the (* 1 x) part -- when is that not equal to just x?

otfrom15:05:47

@U04V70XH6 you'd be right of course. I should maths more.

korny12:05:57

It also helps that I'm a consultant so not generally filling a full time role. But honestly, most full time jobs could be done in 4 days. I'm far more efficient 4 days a week than 5.

👍 8
agile_geek13:05:30

I need to get the actual dates sorted but I’ve a friend (some of you have met her - Fiona) whose organising a general tech conference “Build IT Right” in Newcastle in November. CfP will probably be in next few weeks but it anyone fancies a visit to the Toon (should be a budget for expenses for speakers) then I urge you to submit some talks. I’ll post details here once I get more from Fiona. P.S. I’m already budgeting for a decent bottle of wine and a few beers to bribe the two members of the programme committee I know to get one of my talks in!

👍 16
alexlynham15:05:57

what's the theme?

agile_geek15:05:27

@alex.lynham It’s general IT conference so anything related to s/w development and development practices but they’re still working on the streams. There will most likely be an Agile/Lean stream, a UX/UI design stream but I’ve suggested a general Developer stream and maybe architecture.

alexlynham18:05:15

Ooh, I might have something by then in that case

mccraigmccraig15:05:49

a nice non-confrontational talk entitled "why you should all stop whining about the parentheses stat and get with lisps right now"

😱 8
😂 16
😍 16
peterwestmacott15:05:35

OTOH the parens are like walls around our sacred code protecting it from those that would judge a book by its cover

mccraigmccraig15:05:18

the problem is that many would be excellent developers are insulated from a beneficial exposure to s-expressions by the cloud of baseless derision generated by all those with unthinking attachments to semicolons

otfrom15:05:59

@mccraigmccraig surely the less confrontational title is "All wrong languages have too much syntax"?

mccraigmccraig15:05:46

@otfrom yes, but the "non-confrontational" bit was a lie 🙈

otfrom15:05:17

fair enough

otfrom15:05:56

I still feel it is important to place the incorrectness where it belongs, which is with the wrong languages rather than those who don't see the beauty in minimal syntax 😉

otfrom15:05:45

(btw, I think other languages are great. I'm just being silly. Pls don't hurt me or take this out of the context of here where being silly about smug lisp weenie history is OK)

4
3Jane15:05:02

what you mean is, some of your best friends are other-languages-programmers? 😜

agile_geek15:05:13

@mccraigmccraig you can’t submit that talk…it’s already on my list!

otfrom15:05:23

oh heavens no. I would never speak to them. I feel a great affection for them despite the way they cling to error.

otfrom15:05:38

I'm no hammer of the heretics.

otfrom15:05:49

(omg, this is getting worse and I feel I'm being encouraged now)

agile_geek15:05:29

@otfrom you used to speak to me when I didn’t grok Clojure!

mccraigmccraig15:05:10

@agile_geek i'll code-golf you for it!

😂 4
🍿 4
3Jane15:05:28

I saw a great video recently about how religious people are the ultimate nerds, but programmers would likely place in 2nd place 🙂

3Jane15:05:40

incidentally

3Jane15:05:57

repl is modifiable, right?

guy15:05:37

what do you mean sorry

mccraigmccraig15:05:43

there are few places in life or software where one thing is objectively better than another thing - s-expressions in place of more syntax is one of those places and yet...

💯 8
👍 8
metal 8
3Jane15:05:54

I wonder whether people’s minds would be suddenly blown if you could get it to understand [] instead of ()

3Jane15:05:58

or have the parser switch the first symbol encountered with a boundary, if exists later, and allow people to write conj(item, collection)

3Jane15:05:25

also: I wonder how much the speaker’s language influences how they read code

3Jane15:05:46

S-V-O versus S-O-V (where the “active” part is located)

otfrom15:05:19

(tho that was great timing to have to go to another window)

otfrom15:05:39

java is great b/c it had beanshell which was almost like a repl

otfrom15:05:57

and java was about as far as Sun thought they could take C++ programmers to lisp and smalltalk

agile_geek15:05:17

Seriously tho, there has to be a ‘Lisp is all conquering’ talk in me somewhere. Just need to write more parens until it surfaces.

korny15:05:36

I just remembered - that language spreadsheet needs a "has a decent repl" column. Will have to add one when I'm not pretending to entertain a toddler

mccraigmccraig15:05:25

i'd go for "has eval" as the fundamental feature @korny

🐘 4
3Jane15:05:26

(better not 😉 )

mccraigmccraig15:05:39

it's quite interesting to read the reasons for rejections of different compiler backends for lux in the "sad little pile of bad ideas" column https://trello.com/b/VRQhvXjs/lux

👍 4
rhinocratic16:05:48

Some of the reasons seem perhaps a little... specious? Maybe that's too strong a word - I suppose the explanations lack context!

mccraigmccraig16:05:51

he's got too much to do no doubt - but i was surprised that go doesn't have any eval for some reason

rhinocratic16:05:27

My limited experience with it (6 months) suggests that Go lacks many things, but I suppose it's intentionally a small language. My estimation so far would be "good in parts"!

dominicm16:05:35

I guess the party parrot didn't click his gdpr email and can't be included anymore.

mccraigmccraig16:05:16

since this API integration i need to do is all SOAP @lady3janepl it looks like i might be porting my rsxml thing to clojure rather soon

3Jane16:05:05

not sure whether to say I feel for you because soap, or yay, more useful stuff in clojure 😄

mccraigmccraig16:05:23

i did Exchange Web Services SOAP with that ruby rsxml lib a while back, and it was ok - building everything with vanilla ruby datastructures was great - very easy to test, and no need for SOAP ceremony in most of the code

agile_geek16:05:29

I wash my hands with SOAP tumbleweed

otfrom16:05:08

I wash my hands with CORBA

dominicm17:05:57

I charm CORBA with my flute

😂 8
thomas18:05:13

I do none of those things...

mccraigmccraig19:05:01

s-expressions make a better xml

👍 8
mccraigmccraig19:05:56

i wonder if any of the hiccup processors will do the transformation for me

mccraigmccraig19:05:59

hmm. although i didn't know about data.xml until now

mccraigmccraig19:05:22

sometimes the universe seems benevolent

alexlynham20:05:23

Fwiw offtopic but if you're doing json, jsonista is mad fast compared to data.json or Cheshire

korny21:05:57

Interesting. Not that speed of json processing has ever been my bottleneck for anything - if I’m doing JSON, I’m probably doing I/O so I’m probably spending far more time on that than string manipulation!

korny21:05:39

Clojure gripe-du-jour (gee, it’s fun to be back!) : case doesn’t work with Java enums. You have to use condp or (case (.getName enumThing) or a specially manufactured macro.

dominicm21:05:49

The special macro tastes good