I am new to Clojure, although I am familiar with functional languages, mainly Scala.
I'm trying to figure out what the idiomatic way of working with collections in Clojure is. I am particularly confused by the behavior of functions such as map .
Scala pays great attention to ensuring that map always returns a collection of the same type as the original collection, if that makes sense:
List(1, 2, 3) map (2 *) == List(2, 4, 6) Set(1, 2, 3) map (2 *) == Set(2, 4, 6) Vector(1, 2, 3) map (2 *) == Vector(2, 4, 6)
Instead, in Clojure, as I understand it, most operations, such as map or filter , are lazy, even if they are called in impatient data structures. This has a weird result.
(map
lazy list instead of vector.
While I prefer, in general, lazy operations, I find this confusing. In fact, vectors guarantee certain performance characteristics that are not listed.
Let's say I use the result above and add the end. If I understand correctly, the result is not evaluated until I try to add it, then it will be evaluated, and I will get a list instead of a vector; so I have to go through it to add to the end. Of course, I could turn it into a vector afterwards, but it becomes messy and can be missed.
If I understand correctly, map is polymorphic, and it will not be implemented so that it returns a vector to vectors, a list in lists, a stream on streams (this time with lazy semantics), and so on. I think I'm missing something about the basic design of Clojure and its idioms.
What is the reason that basic operations on Clojure data structures do not prevail over the structure?