Search code examples
clojure

Accumulate values to a list


I'd like to create a list depending on the results of some functions. In Java (my background), I'd do something like:

List<String> messages = ...

if(condition 1)
   messages.add(message 1);

if(condition 2)
   messages.add(message 2);

...

if(condition N)
   messages.add(message N);

In clojure, I think I'll need to create a list using let like the following (just dummy example):

(let [result
  (vec
    (if (= 1 1) "message1" "message2")
    (if (= 1 0) "message3" "message4"))]
result)

I've also checked cond but I need to be appending the elements to the list considering all the validations (and cond breaks after one condition is satisfied).

Which way should I follow to achieve this?


Solution

  • If you want them to be conditionally added like in the Java example, you could use cond->, which does not short circuit:

    (let [messages []]
      (cond-> messages ; Conditionally thread through conj
        (= 1 1) (conj "Message1")
        (= 0 1) (conj "Message2")
        (= 0 0) (conj "Message3")))
    
    => ["Message1" "Message3"]
    

    If you want to conditionally add one or the other like your second example suggests however, you could just use plain conj with some if expressions:

    (let [messages []]
      (conj messages
        (if (= 1 1) "Message1" "Message2")
        (if (= 0 1) "Message3" "Message4")))
    
    => ["Message1" "Message4"]
    

    And I'll note that your original attempt almost worked. Instead of vec, you could have used vector, or just a vector literal:

    (let [messages [(if (= 1 1) "Message1" "Message2")
                    (if (= 1 0) "Message3" "Message4")]]
      messages)
    
    => ["Message1" "Message4"]
    

    Although, this is would only be beneficial if you didn't already have a messages populated that you wanted to add to. If that was the case, you'd have to use concat or into:

    (let [old-messages ["old stuff"]
          messages [(if (= 1 1) "Message1" "Message2")
                    (if (= 1 0) "Message3" "Message4")]]
      (into old-messages messages))
    
    => ["old stuff" "Message1" "Message4"]