Thursday 18 August 2016

Breaking: Groovy and Clojure answers for that array-look-up code puzzle

Well it's not really that breaking really... what I mean is a coupla other people posted some answers to last week's code puzzle after I wrote up the results ("Looking at the code from that code puzzle last week"). I was gonna just append them to the bottom of that earlier article, but hen no-one would see them, and that seemed a bit disrespectful. Also for this blog which is still mostly read by CFML devs, it's some exposure to other languages you might want to take the time to look at, and these are good examples why.


I was wondering what happened to Sean's Clojure example, but he was off leading his life instead of clearing away the cobwebs from my blog, so didn't notice the code puzzle initially. But here's his Clojure code (fully annotated for us non-Clojurians):

;; simplest solution to find first match -- note that `filter` returns
;; a lazy chunked sequence so it will not search the entire vector
;; however, the chunks are 32 elements in size so it will search up
;; to 31 elements beyond the first match
(first (filter #(re-find #".+at" %) ["at" "cat" "scat" "scratch"]))

;; Clojure has `some` but it returns the result of applying the predicate
;; not the original element so we need to write a "smarter" predicate:

;; will not work in all cases:
(some #(re-find #".+at" %) ["at" "cat" "scat" "scratch"])
;; this: (some #(re-find #".+at" %) ["scratch" "at" "cat" "scat"])
;; produces this: "scrat" -- oops!

;; will work with extended predicate:
(some #(when (re-find #".+at" %) %) ["at" "cat" "scat" "scratch"])

;; or we can use reduce with an early return -- the `reduced` value:
(reduce (fn [_ s] (when (re-find #".+at" s) (reduced s))) nil ["at" "cat" "scat" "scratch"])

;; a note about notation: #(.. % ..) is shorthand for (fn [x] (.. x ..))
;; i.e., an anonymous function with one argument

That looks like a bunch of code, but it's also four examples:

(first (filter #(re-find #".+at" %) ["at" "cat" "scat" "scratch"]))

(some #(re-find #".+at" %) ["at" "cat" "scat" "scratch"])

(some #(when (re-find #".+at" %) %) ["at" "cat" "scat" "scratch"])

(reduce (fn [_ s] (when (re-find #".+at" s) (reduced s))) nil ["at" "cat" "scat" "scratch"])

Now I've only had the most superficial look at Clojure, but even I can just read what's going on in that code. So that's cool. I've been off my game recently with my out-of-hours tech stuff - in case you hadn't noticed - and I really want to finish finding my motivation to get back to it, and look at more Clojure. I think it's a good thing to look at for a perennial CFMLer or PHPer as its quite the paradigm shift, but still seems pretty easy to get at least a superficial handle on, and then work from there.


Tony's done a Groovy example. Every time I see Groovy, it just seems cool. Check this out:

print( ['a', 'at', 'cat', 'scat', 'catch'].find { it ==~ '.+at' } )

That's it. Done. 67 characters, most of it data. 25 characters of actually "doing stuff", including more whitespace than I'd usually use for this sort of thing. Doesn't that make you want to use Groovy?

Anyway, that's that. I just wanted to share that code with y'all.