0

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)))
0

4 Answers 4

1

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))
Sign up to request clarification or add additional context in comments.

1 Comment

I realized that strings are seqable, so the second two examples won't solve your specific problem. cond is the way to go.
1

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.

Comments

0
#(if (string? %)
   0
   (count %))

Comments

0
(defn alex
  [obj]
  (cond
    (string? obj) 0
    (number? obj) 0
    :otherwise (count obj)))

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.