Okay
Okay
Okay…
It’s better that you break your function into smaller ones, each does one simple purpose. Clojure is functional, isn’t it?
I’m just kidding. Sometimes it’s really hard to write such that code. Consider this example, I have a function for validating whether a string is a valid date time string. If it’s nil or blank, just skip it, otherwise, try parsing it to see if it’s okay.
(defn validate-date-time [date-time]
(if (nil? date-time) true
(if (blank? date-time) true
(try (f/parse formatter date-time)
true
(catch Exception e false)))))
Nested, nested and nested. If this is still simple and easy to see for you, try this one, need to check if the date time is between 1970 and 2030
Ehhh…
Okay, stop here! I don’t want my head to be blown up by these nested parentheses. This makes me remember the js callback hell days before Promise age. It’s much better if we can write something like this, like what we usually do in other programming languages
Hmm, much better huh? Unfortunately, we don’t have anything called early return
in Clojure. We can do a little hack using try
, catch
but they support only
for throwing and catching exception.
Luckily, I found slingshot, an Enhanced throw and catch for Clojure that allows you to throw anything to the catch block. What you need to do is just to wrap your code inside its try and catch block and throw whatever value you want to return. The above evil code can be transformed into this
Phew! We still have one nested level at the let
block but it’s much better
compared to the original one. I think that’s how Clojure do block scoping
and we have no other way to re-assign the variable so we cannot avoid that
nested level, but it’s still better than writing the nested if
blocks.
That’s how I do early return in Clojure. Once again, thanks slingshot
for
making this possible! :D