Budi Sutrisno
Budi Sutrisno

Reputation: 727

clojure way on flow control statement

Suppose I have a python function like this:

def required(value):
    if value is None:
        throw Exception
    if isintance(value, str) and not value:
        throw Exception
    return value

Basically I want to check if the value is null or not. If the value is a String, also check if it's empty or not.

What is the clojure way of doing something like this?

Upvotes: 2

Views: 641

Answers (4)

n2o
n2o

Reputation: 6477

The Clojure way of doing something like this is not to throw exceptions or so. The idiomatic way would be something that returns nil and nothing else.

So my advise: Do this without exceptions.

Your function will then look like this:

(defn required [value]
  (when (string? value)
    value))

It checks for the type of value and returns nil if it is not a String. Otherwise return your value.

Or if you want an error message in your terminal:

(defn required [value]
  (if (string? value)
    value
    (println "Value must be a String.")))

Note that println prints the String and then returns again nil.

Upvotes: 5

Dave Yarwood
Dave Yarwood

Reputation: 3010

A. Webb is right on the money in that pre-conditions are a great, idiomatic way to represent what you're trying to do here.

For what it's worth, here is how you would do the same thing using explicit exception-throwing and a condition statement:

(defn required [value]
  (cond
    (not (string? value))
    (throw (IllegalArgumentException. "Value must be a string."))

    (empty? value)
    (throw (IllegalArgumentException. "String cannot be empty."))

    :else
    value))

Or, perhaps more idiomatically, handle the errors first using when, then return the value at the end:

(defn required [value]
  (when (not (string? value))
    (throw (IllegalArgumentException. "Value must be a string.")))
  (when (empty? value)
    (throw (IllegalArgumentException. "String cannot be empty.")))
  value)

Upvotes: 2

A. Webb
A. Webb

Reputation: 26446

Preconditions would do the trick nicely in this instance. Otherwise use Clojure's control flow special forms/macros, e.g. if, cond with throw.

user=> (defn required 
         [value] 
         {:pre [(string? value) (not-empty value)]} 
         value)
#'user/required

user=> (required nil)
AssertionError Assert failed: (string? value)  user/required ...

user=> (required "")
AssertionError Assert failed: (not-empty value) ...

user=> (required "foo")
"foo"

Upvotes: 5

DanLebrero
DanLebrero

Reputation: 8593

Both previous answers are slightly wrong on the assertions. I what Budi is asking for is:

(defn required [value]
  (if (or (nil? value)
          (and (string? value) (clojure.string/blank? value)))
    (throw (Exception.))
    value))

Upvotes: 4

Related Questions