2

I am trying to return a list from a let statement.

(let [data []]
 (doseq [x ["0" "1" "2" "3" "4"]]
  (into data (do-stuff x))) data)

However the data list is always empty.

I checked this answer on returning values from the let scope however could not fix this.

Community
  • 1
  • 1
Droidekas
  • 3,464
  • 2
  • 26
  • 40
  • `data` is immutable - if you want to return `["0" "1" "2" "3" "4"]` you can just return it directly instead of trying to copy it to a new list. – Lee Feb 21 '16 at 15:46
  • this was just an example,the `["0" "1" "2" "3" "4"]` is a varible which could be any list – Droidekas Feb 21 '16 at 15:47
  • Right, but whatever the list is you can just return directly since it is immutable. – Lee Feb 21 '16 at 15:49
  • Edited the question,I need to perform a funciton on x too – Droidekas Feb 21 '16 at 15:51

2 Answers2

4

If you are trying to understand the looping mechanism in Clojure, you are probably looking for this (assuming that what you are doing is just an exercise in how collections work):

(for [x ["1" "2" "3"]] x)

The result is:

("1" "2" "3")

Of course, if this is all you are going to do, you already have the collection and don't need to build it.

Based on your edit, do this:

(for [x ["1" "2" "3"]] (do-stuff x))

There are many other ways to do this type of stuff though, like using map or reduce and other tools, depending on the complexity of do-stuff and what it needs access to.

Remember, values in Clojure are immutable be default. You cannot mutate your data at all, it is fixed at a value of []. Unless you make it an atom, which is unnecessary for what you need. Functional programming is about building values, not mutating variables.

There are many ways to express what you are trying to do, but for is the list-building ("list comprehension") version of do-seq as they share the same general structure. Since your question was about do-seq, I discuss for for good measure. But map is a better choice here. If you really need it to be a vector as opposed to a lazy sequence, then use mapv.

If you needed something called data that holds these results, then just do this:

(let [data (for [x ["1" "2" "3"]] x)] ;;or map, etc
   ;;do something with data
 )
johnbakers
  • 24,158
  • 24
  • 130
  • 258
4

If you want to modify each element and return a vector you can use mapv:

(mapv do-stuff ["0" "1" "2" "3" "4"])

or you can use map if you just need a sequence output:

(map do-stuff ["0" "1" "2" "3" "4"])

or a for expression:

(for [x ["0" "1" "2" "3" "4"]] (do-stuff x))

for expressions return a sequence which you can convert into a vector using vec if required:

(vec (for [x ["0" "1" "2" "3" "4"]] (do-stuff x)))
Lee
  • 142,018
  • 20
  • 234
  • 287