Fork me on GitHub
#clojure-uk
<
2019-09-06
>
seancorfield06:09:47

Fun plans for the weekend?

seancorfield06:09:48

The wife's away (in China) so I'll probably spend most of my weekend working on HoneySQL... and trying to finish the (long) "lessons learned" blog post I started about my takeaways from eight years of maintaining clojure.java.jdbc...

👍 4
dharrigan06:09:36

I do like HoneySQL 🙂

seancorfield06:09:43

Thanks. Any frustrations with it?

dominicm23:09:29

Automatic camel casing

dominicm23:09:51

I type what I mean, so do what I mean

seancorfield01:09:01

Not sure what you mean @U09LZR36F HoneySQL doesn't do camel casing...

dominicm06:09:08

It does, of table names

seancorfield06:09:50

Nope

user=> (require '[honeysql.helpers :refer :all] '[honeysql.core :as h])
WARNING: update already refers to: #'clojure.core/update in namespace: user, being replaced by: #'honeysql.helpers/update
nil
user=> (-> (select :*) (from :some-table) (h/format))
["SELECT * FROM some_table"]
user=> (-> (select :*) (from :some_table) (h/format))
["SELECT * FROM some_table"]
user=> 
It converts - to _ but you can turn that off.

seancorfield06:09:33

user=> (-> (select :*) (from :some-table) (h/format :allow-dashed-names? true :quoting :mysql))
["SELECT * FROM `some-table`"]
user=> 

dominicm06:09:53

Sorry, that's what I meant (and forgot, I knew it changed).

dominicm06:09:03

I know I can, but I find that kind of api design very frustrating. Maybe it's just me. I prefer the closest relationship between what I type and what happens possible.

seancorfield06:09:22

If you don't ask for quoting, the - is going to be illegal in most database tho', right?

seancorfield06:09:39

(and "good morning, Dominic!" 🙂 )

seancorfield06:09:16

I mostly agree with you tho'... this is why next.jdbc's default is "as-is" (albeit qualified keywords) rather than clojure.java.jdbc's somewhat weird default of forcing lower-case on columns.

dominicm06:09:49

Not in mysql, as I discovered when I was helping someone :)

seancorfield06:09:22

Hahaha... well, much as I love MySQL, it's a weird, non-standard beast.

dominicm06:09:26

Yeah, love that about next.jdbc, I got rather frustrated using h2 with c.j.j

dominicm06:09:47

Morning :) I'm in my new house and very excited. Despite limited sleep.

dominicm06:09:05

It is. I'm ready to burn it with fire to be totally honest :)

seancorfield06:09:17

Like the table names are case-sensitive if the O/S is case-sensitive but column names are case-insensitive and even value equality on strings is case-insensitive (by default, at least on early versions).

seancorfield06:09:46

I must admit, because we have some weird legacy conventions in our MySQL DB, I've started to adopt these as default options:

(def ^:private jdbc-options
  "The default set of options to pass to next.jdbc so that we get
  kebab-case identifiers and snake_case entities."
  {:builder-fn rs/as-modified-maps
   :column-fn ->snake_case
   :label-fn ->kebab-case
   :qualifier-fn ->kebab-case
   :table-fn ->snake_case})

seancorfield06:09:13

This doesn't help with all of our tables, but it makes our more recent decisions more tenable. We have a lot of legacy camelCase table and column names 😞 I hate our database to be honest!

seancorfield06:09:37

Of course, if we were starting fresh, we'd probably use Datomic 🙂

dominicm11:09:15

I'm looking forward to a stable crux, a lot of my ideas are "oh, let's store this for later. Might be handy".

dharrigan06:09:12

Let me ponder, nothing comes to mind at the moment (still a newcomer...). I suppose the only thing that would have helped is whether I can enable debug/trace logging of the SQL that is being flung out (but perhaps that is a log configuration?)

dharrigan06:09:21

also, it wasn't clear, until I started used it, that the results that it returns are namespace qualified maps, had to read-and-re-read and try the documentation to discover that

dharrigan06:09:39

but these are minor, probably just-getting-to-know-it, thingimabobs

seancorfield06:09:41

You could always write your own logging wrapper for honeysql.core/format -- since you have to call something to turn the data structure into SQL.

seancorfield06:09:02

Not sure what you mean about the "namespace qualified maps" -- that doesn't sound like HoneySQL stuff?

dharrigan06:09:29

I'll get an example, but right now, just heading out the door to work 🙂

seancorfield07:09:04

Do you mean next.jdbc returns namespace qualified maps by default? (I thought the docs for next.jdbc made that pretty clear -- but suggestions for improvements are welcome!)

dharrigan07:09:30

I was mixing the two- since they work so really well together 🙂

dharrigan07:09:36

(I wonder why.... 🙂 )

dharrigan07:09:37

Well, just had a look at the code I wrote using honeysql

dharrigan07:09:50

can't think of anything that I would suggest atm, it just works! 🙂

seancorfield07:09:38

That's great to hear @U11EL3P9U -- I'll try not to break it with any future changes 😉

dharrigan08:09:54

Oh I do like a bit of i3wm in the morning 🙂

rickmoynihan08:09:37

I love tiling window managers… Having tried almost all of them XMonad was my favourite. Having to use Amethyst on macos, which is a poor substitute for any of the proper ones.

dharrigan08:09:51

once you use tiling, you won't go back 🙂

dharrigan08:09:00

such a great window manager

seancorfield08:09:21

Microsoft have released an open source version of PowerToys for Windows 10 which includes an interesting take on "window management"...

seancorfield08:09:43

(I'm loving it for my use case)

maleghast09:09:34

Morning All - it's Friday!

thomas09:09:45

YEAH TGIF

😍 4
🎵 4
2️⃣ 4
👂 4
jasonbell09:09:44

I like working on Friday.

jasonbell09:09:58

It’s always good to know it’s three working days to Monday.

Ben Hammond10:09:58

Ha! once again I find myself regretting my previous use of optional params thus

(defn my-fn [param1 & {:keys [opt1 opt2]}]
becomes
(defn my-fn 
  ([param1] (my-fn param1 nil)) 
  ([param1 {:keys [opt1 opt2]}]
   ...)

Ben Hammond10:09:16

this is is recurring theme for me.

Ben Hammond10:09:47

I almost always experience this same remorse after introducing optional parameters

Ben Hammond10:09:05

I assume its not just me....

Ben Hammond10:09:39

under what circumstances has optional params to be a good choice?

mccraigmccraig10:09:02

well you could do (defn my-fn [param1 & [{:keys [opt1 opt2]}]] ...) for a similar result

mccraigmccraig10:09:30

although i favour the dual-arity version, but only 'cos i find it easier to read and "easier to read" is partly a feature of familiarity, so it's not necessarily a particularly sound reason

mccraigmccraig10:09:26

i just agd over our codebase with (\ |\[)\&\ and found a couple of useful cases for rest-args

mccraigmccraig10:09:44

[1] macros with [... & body]

👍 4
mccraigmccraig10:09:20

[2] proxy functions with [& args] which forward all their args to another fn

👍 4
mccraigmccraig10:09:16

but we don't have any use of the map destructure on rest-args - i really don't like it

otfrom17:09:44

I use rest args a fair bit

folcon11:09:45

There are times when you just want to shove args at a function, though to be honest I tend to do:

(defn my-fn [param1 {:keys [opt1 opt2] :as opts}]...)
(not that I’m certain it’s a good pattern, I just find it useful as I’m destructuring a map anyway) I rarely make the opts actually optional and do as you did…
(defn my-fn
([param1] ...)
([param1 {:keys [opt1 opt2] :as opts}]...)

danielneal11:09:29

I definitely prefer multiple arity versions

dharrigan14:09:24

I really really dislike twitter's resetting of my "show latest tweets" to "show top tweets"

dharrigan14:09:44

I never want to see top tweets, only the latest, so I wish it wouldn't reset after a time

mccraigmccraig15:09:44

omfg CIDER with the shadow-cljs node-repl is a real eye-opener

mccraigmccraig15:09:56

it's the cljs repl i've been waiting for forever

folcon11:09:45

There are times when you just want to shove args at a function, though to be honest I tend to do:

(defn my-fn [param1 {:keys [opt1 opt2] :as opts}]...)
(not that I’m certain it’s a good pattern, I just find it useful as I’m destructuring a map anyway) I rarely make the opts actually optional and do as you did…
(defn my-fn
([param1] ...)
([param1 {:keys [opt1 opt2] :as opts}]...)