Reputation: 53481
Why do people prefer list comprehensions like
(for [x '(1 2 3)] (* 2 x))
instead of (map #(* %1 2) '(1 2 3))
?
Are there benefits to this kind of programming?
1. Is it more readable?
2. Is it faster in some cases?
3. Is it better for certain kinds of operations and data structures?
Upvotes: 4
Views: 477
Reputation: 49208
First of all, list comprehensions are just syntactic sugar, so there should be no inherent difference apart from readability.
But note that list comprehensions actually unify at least three higher-order functions, namely map
, filter
and concatMap
into one syntax. So in non-trivial cases where one would need complex combinations of these, the syntax can have big readability advantages.
Besides that, one can conveniently use value bindings to store results and make things even clearer:
[ (x, y) | x <- [1..10],
y <- [1..10],
let dist = (x - 5)² + (y - 5)²,
dist < 10² ]
But anyway, list comprehensions can be made much more general than just processing lists. Basically, they can process any Monad
using a uniform and convenient syntax. F# for example even extends this into controlling arbitrary programm flows.
Secondly, being even more abstract than the usual higher-order functions, list comprehensions could actually be faster, because the compiler can take advantage of optimization laws that would otherwise be up to the programmer to be considered.
[ x + 1 | x <- numbers, even x ]
The straightforward translation would be
map (\x -> x + 1) (filter even x)
where the list is iterated through twice, producing a worthless intermediate result.
The compiler however could recogize and optimize the above pattern and produce a direct, optimized filterMap
version.
Upvotes: 1
Reputation: 32264
I know this is a Clojure question, but the book "Programming in Scala" by Martin Odersky, et al, has a nice discussion about how for
comprehensions map to the map
and filter
functions.
Upvotes: 0
Reputation: 27164
List comprehensions are merely "syntactic sugar" over standard functional programs but they give an intuitive reading of common operations over lists. -- Guy Lapalme
Their only intent is better readability. Don't expect any significant performance improvement by using them.
This paper give some insights into implementing List comprehensions in Lisp like languages.
Upvotes: 2
Reputation: 91534
list comprehensions are used for cases where you need to iterate through sequences in more complex ways. in your example they are the same so I would recoment map because its easier to read.
map cant gets ugly for do this for example:
(for [x '(1 2 3) y '(3 2 1)] (* 2 x y))
Upvotes: 0
Reputation: 101555
For your given example, there are no benefits; but in general, for
is useful when you're joining two (or more) sequences, or when you need to do some filtering - a for
with :let
and :when
is usually more readable than a chain of nested map
and filter
.
Upvotes: 8