Fork me on GitHub

Good Morning!


Morning chaps!

Jakob Durstberger08:03:08

Morning ๐Ÿ™‚


After nearly a year off of Clojure Iโ€™d forgotten just how lovely it is to write :-)

โค๏ธ 20


Edward Hughes10:03:19

@mattford certainly is. I think I've actually noticed messing around with paredit has the same kind of soothing tactile effect of a fidget spinner, aside from letting me write and edit from a higher level of abstraction.


Say you have a number of vars that you want to then use in a function, but only if each var is not null, like this:


(when foo (function foo))
(when bar (function bar))
(when baz (function baz))


is there a better way?


(i.e., guarding the execution of the function if by some misconfiguration, the var is nil)

Ben Hammond11:03:27

(keep function [foo bar baz]) ? is lazy, which might not be what you want


ah, umm, sorry, the function is different each time


(when foo (functionA foo))

Ben Hammond11:03:05

nah what you wrote is optimal for clarity then


(when bar (functionB bar))


always nice to invoke the crowd wisdom ๐Ÿ™‚

Ben Hammond11:03:57

but you might want your functions to tolerate nil

Ben Hammond11:03:04

that's a more clojurey thing to do

Edward Hughes11:03:19

nil-punning, you mean?


Yes, true, but those functions call into 3rd party libaries (with the var passed in) so I don't know how they will behave ๐Ÿ™‚

Ben Hammond11:03:31

ah fair enough then


I'll have a peek of their source code however


Yes, as a rule, when I write my own functions, they tend to handle nil puning well ๐Ÿ™‚


(thanks to the fact that clojure core fucntions handle nil puning well)


You could add a higher-order function, that makes a fn nil-punnable?


(defn make-nil-punnable [f] (fn [x] (when x (f x))))


Or maybe some-> to โ€œshort-circuitโ€ out of nil

Edward Hughes11:03:33

I actually found a neat trick from SICP where they talk about how to use unless and lazy eval to deal with nils when doing something like dividing by your argument in a test form. Iirc, with lazy eval specifically, unless basically isolates your nil case before it gets sent to the test.


Seems to me this is a bit like working with Maybe or Option types in typed FP, and AFAIK some-> is the closest clojure analogue to bind (or whatever itโ€™s called), which you would use in those cases?


(when (not-any? nil? [foo bar baz]) ... ) perhaps?


use fnil to deal with the nil punning on functions you don't own?

Edward Hughes11:03:42

Isn't the when and the not-any? nil? redundant there, aside from wrapping everything in a single form for the when? If the when form gets a test from [foo bar baz] that evaluates to nil, it's going to not call the function that doesn't play well with nil.


My intention was that the body of the when would contain the three functions in a context where they could all safely be used. I assumed the when's were nested.


how would fnil work?


never used that before

Edward Hughes11:03:26

You'd basically give it something to do if it gets a nil for the argument of a function that would break if it tries to do something with the nil. (fnil divide-5-by-arg "Can't divide five by nil") takes the fn in the first position, and any time you give it a nil, it will return the second arg.

Edward Hughes11:03:53

Ach, sorry, I'm mixing things up. I meant nil.

Edward Hughes12:03:14

So you'd just have a defn form with fnil holding the library function you're using, with the "exception" you want it to return if a nil worms its way in.


fnil still calls the fn doesn't it @edward.hughes1911 - so you get to supply default values, rather than swerve the application


so ((fnil inc 0) nil) => 1


Yeah, I think using (when for me atm, makes the intention clear

Edward Hughes12:03:35

Yeah it still calls it, but with whatever you supply as x. I was thinking of doing string stuff so my mind jumped to returning an error message or something.


I'll add fnil to my memory banks ๐Ÿ™‚

๐Ÿ™‚ 4
Edward Hughes12:03:56

when is the most elegant solution, I would agree.


how about this @dharrigan

(defmacro when-apply [f & args] `(let [v# [ [email protected] ]] (when (every? some? v#) (apply ~f v#))))


(when-apply + 1 2) => 3


(when-apply + 1 nil) => nil


I think I'll stick with (when foo (functionA foo)) ๐Ÿ™‚


not that I don't appreciate the response ๐Ÿ™‚


obvs it's also fine as a plain-old-fn (defn when-apply [f & args] (when (every? some? args) (apply f args)))


but the double evaluation of args was bugging me ๐Ÿ˜ฌ


Could you elaborate a bit more on the double evaluation? Everybody is always telling me if I can use a function I shouldn't use a macro, and I strongly believe we are missing out by not using macros more.. Your double evaluation of args argument is one no body has put on the table.. but now that you've mentioned I think I remember SICP referring to it.. (I'll need to brush it up).. Still I'd like to hear more on what you meant if you don't mind ๐Ÿ™‚


E_INSUFFICIENT_COFFEE - it was just me being dim... args isn't double-evaluated in the fn form...


hmm ok, no worries.. I thought I could have found a reason to push a little more for macros.. In any case, thanks ๐Ÿ˜„


there are definitely good times to use macros


Coming from Java, learning that code can be data and vice versa, and that that allows for marcos; and then everyone is hammering down that macros are filth.. One feels not encouraged to use them, not even to learn about them.. Luckily I hate all dogmatism and I like to challenge the status quo, so I don't let the hammering down stop me to try to find out what is this conspiracy against macros.. Specially when it feels like it is one of LISP's secret weapons.. Who in their sane mind would argue against a secret weapon? ๐Ÿ™‚


a quick ag across our monorepo: defn:6139, defmacro:73 ... we use them, but not that often - but one or two of those 73 macros i think will be the most common non-core constructs we use


Thanks! I'll take a look to the ratio at work! ๐Ÿ™‚

Wes Hall13:03:39

Interestingly I am working on something a little similar @dharrigan. The new builder objects in v2 of the AWS API for Java are a little inconsistently weird. Mostly you can chain them with (..) but it seems that some of them behave differently between setting a value = nil and not setting it at all. I sort of need a cond version of the .. macro, but it doesn't exist, so I have been dusting off my macro-fu ๐Ÿ™‚. Probably I could just drop the .. and use whens but it's an exercise ๐Ÿ™‚

Wes Hall13:03:15

You may, by the way, want when-some unless you want the function not to be called when foo = false (as well as nil).


not saying it is any better than using when but you can use and: (and foo (fn-a foo)) exploiting the fact that and returns the value of the last expression if all previous are truthy


i quite like using and like that - but i also keep forgetting it's a thing and have rediscovered it several times

๐Ÿ˜€ 4

Hello everyone - how are you all doing? Sorry I've not been around; busy, busy, busy!

๐Ÿ‘‹ 4

that is encouraging @mccraigmccraig;)


Just a reminder that ClojureBridge London content has some really small issues that could use your help to improve our content. Its a good way to practice contributing to an open source project (and good for your CV if you are job hunting) Thank you


one obvious caveat with and that if the param is boolean this is just not a good idea. applies to vanilla when too tho




If you do multiple things in your when then and is not a perfect replacement either.

Wes Hall16:03:14

Anybody have a particularly elegant way of doing distinct-with? As in, remove all values that return the same value when applied to a given function. Right now I am thinking group-by then first on each val, but I am sure a greater magic probably exists.

Ben Hammond16:03:33

does it need to be the first encountered that wins? Can it be any old one?

Wes Hall16:03:07

Any old one would be fine in this instance.

Ben Hammond16:03:54

(doc medley.core/dedupe-by)
([f] [f coll])
  Returns a lazy sequence of the elements of coll, removing any **consecutive**
  elements that return duplicate values when passed to a function f.
=> nil

Ben Hammond16:03:14

oh sorry missed the consecutive

Ben Hammond16:03:55

(defn distinct-with
  [f coll]
  (vals (zipmap (map f coll) coll)))
=> #'user/distinct-with
(distinct-with odd? (range 10))
=> (8 9)

Ben Hammond16:03:17

not particularly an improvement over

(defn distinct-with2
  [f coll]
  (map first (vals (group-by f coll))))

Wes Hall16:03:36

Yeah, either is probably fine. Same diff I guess. Both read pretty well. Thanks ๐Ÿ™‚


Is there a classic book/paper on the design/architecture of the JVM?

Wes Hall17:03:52

@mattford It's still on my "to read list", but Ben Evans (aka Kittylyst) is my goto dude on all things JVM magic. His book, "Java: The legend" has a section on the JVM and its design including all the JIT and GC magic. It's probably worth a read. Some years back he was doing classroom courses on JVM internals which was pretty fascinating but that was in the jClarity days and I doubt he's still running them unfortunately.

๐Ÿ‘ 8
Wes Hall17:03:29

In other news, (tree-seq) is a fun thing ๐Ÿ™‚


@mattford There was a chap called Kirk Pepperdine he used to write on Java performance tuning, knew the JVM very very well. That long since Iโ€™ve looked for any of his stuff as that last stuff I did for JDJ was 2002/2003.

๐Ÿ‘ 4

Medley has distinct by

Ben Hammond18:03:09

Does it? That was what I failed to find earlier


Sooo, your local supermarkets, can you still find food, tinned or otherwise, on the shelves?

Edward Hughes15:03:20

Went and did a 150 pound shop at Morrison's the other day. Shelves are brimming as ever.


Yes at the moment


Loads of Italian tomatoes.

Wes Hall23:03:44

My survival plan is based primarily on chocolate eggs. Always plenty of those left.

๐Ÿ˜„ 4
๐Ÿฅš 4

I can confirm that this is true

๐Ÿ˜‚ 4
๐Ÿ‘ 4