Question

I'm writing a function that can input strings, numbers, arrays, Java Collections and Maps. The constraints are the output for both strings and numbers should be zero.

The Clojure function count does everything I need, except handle the constraints. So, I thought to use an if statement to test if the input is a string or a number. Returning zero if the test is true, and using count otherwise. I have workable code for either case, but do not know how to combine the two. Moreover, I am not sure the most efficient way to set up the testing in this case.

  (defn Swanson [a]
        (if (string? a) 0
        (count a)))

  (defn Propello [b]
        (if (instance? Number b) 0
        (count b)))
Was it helpful?

Solution

If clarity is more important than efficiency (and it almost always is), then I'd use cond here:

(cond
  (string? a) 0
  (instance? Number a) 0
  :default (count a))

There's the possibility that what you really want is "the count if it's countable, otherwise 0". In that case, the 'seq' function can help

(if (seq a) (count a) 0)

And if you actually care about performance, doing it with protocols should let you buy into more JVM optimizations in principle. But profile before and after to make sure!

(defprotocol SwansonPropello
  (swanson-propello [a]))

(extend-protocol SwansonPropello
  clojure.lang.ISeq
  (swanson-propello [a] (count a))

  clojure.lang.Seqable
  (swanson-propello [a] (count a))

  Object
  (swanson-propello [_] 0))

OTHER TIPS

Another option:

(defn swanson-propello [x]
  (if (or (string? x)
          (number? x))
    0
    (count x)))

or is the most fundamental form for this type of combining. Its docstring describes it well:

Evaluates exprs one at a time, from left to right. If a form
returns a logical true value, or returns that value and doesn't
evaluate any of the other expressions, otherwise it returns the
value of the last expression. (or) returns nil.
#(if (string? %)
   0
   (count %))
(defn alex
  [obj]
  (cond
    (string? obj) 0
    (number? obj) 0
    :otherwise (count obj)))
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top