Win a copy of The Way of the Web Tester: A Beginner's Guide to Automating Tests this week in the Testing forum!

# Multiple list bindings

jay vas
Ranch Hand
Posts: 407
Hi guys : in a clojure book I saw a for block with two bindings to a lazy list....with variables x and y which were
Not defined. This was odd to me, because I'm wondering how a list could
Be smart enough to do the combinatorial processing necessary for turning this statement into something meaningful.

Here it is : Given z, a lazy sequence of ints....

..... For [x z y z :when (prime?(+ x y ))] .....

Pardon my ignorance ... But How can this code mean anything?

Sean Corfield
Ranch Hand
Posts: 305
11
First off, bindings introduce new local names so (for [x z y z ...] ...) is effectively declaring two new local 'variables' x and y, both initialized to z.

Second, when a for binding has multiple variables being bound, it's like nested loops.

Hope that helps?

jay vas
Ranch Hand
Posts: 407
Okay... Thanks.

So what is the purpose of for?
This seems like an arbitrary behavior?

Is there a theoretical basis for for? Is it designed to deal with combinatorial problems?

jay vas
Ranch Hand
Posts: 407
Also.... Why would one want to bind the same lazy sequence twice?

Wouldn't the second binding be essentially empty- I'm thinking of java iterators here... But maybe Lazy lists
Are circular in clojure?

Sean Corfield
Ranch Hand
Posts: 305
11
Clojure's for lets you iterate over one or more sequences and generate a result based on the values in them. Think of it as a generic convenience for nested maps and filters.

I'm not sure why you think it's "arbitrary behavior" - could you elaborate?

Could you explain why you think "the second binding [would] be essentially empty"? I don't understand how binding x and y to z could produce different results.

Why would you expect those two versions to generate different results?

jay vas
Ranch Hand
Posts: 407
Regarding the 2nd list's emptiness:
Well.... I gueses I don't understand something about the way lazy lists are bound. I would assume that a list maintains internal state of what index it is at. So that if two variables were bound to the same list, then it would muck that state up.

Regarding "for" in general :
Alot of times, its definetly the case that you have to traverse a nested data structure. But there are so many different ways to do this ---- depth first, breadth first, matches, even using heuristics as far as which nodes to traverse ; I'm not sure how "for" is working .... which makes me somewhat wary of applying it. Am I just overthinking it ?

Sean Corfield
Ranch Hand
Posts: 305
11
Remember that data structures are immutable. Traversing a list cannot change it. A lazy sequence is realized just once, as it is needed, regardless of how many processes are traversing it. It might be very hard to write that sort of code in Java but it's inherent in Clojure - and fundamental to the way the language works.

I don't know whether you're overthinking 'for' but look at the equivalences I provided, in particular the mapcat / map example.

jay vas
Ranch Hand
Posts: 407
Thats cool.... this is really helpful.....

So even iterator data structures in clojure are, essentially stateless.

Iteration is a black box, higher level operation ... ok .... thanks

Sean Corfield
Ranch Hand
Posts: 305
11
More accurately, Clojure data structures are not iterators at all. The iteration is handled in the construct outside the data structure so that it knows where it is in the sequence.

Putting the original 'for' loop into Java terms, iterators would be obtained from the collection 'z' and managed behind the scenes with 'x' and 'y' set to successive results from those iterators (in Clojure they're not actually altered, they're just re-bound to subsequent elements of the sequence 'z'). In pseudo-code:

I think the sequence processing constructs in Clojure are probably one of the hardest things to grok if you're thinking in terms of variables and assignments since they completely encapsulate all of that in a way that allows the data structures - and any symbols bound to reference points within them - to be immutable.