unj2
unj2

Reputation: 53481

Is List-Comprehension any better than List-Abstractions?

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

Answers (5)

Dario
Dario

Reputation: 49208

Some general thoughts

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

Ralph
Ralph

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

Vijay Mathew
Vijay Mathew

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

Arthur Ulfeldt
Arthur Ulfeldt

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

Pavel Minaev
Pavel Minaev

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

Related Questions