2

Common Lisp has a powerful Loop macro built in. It's really useful and powerful, and I use it quite often.

I've also heard of a very similar thing, called Iterate. It look really similar to Loop, but has more Lispy feel to it. What are the differences between these two? May there be any reason to switch to any of these, apart from simple preference of style?

MatthewRock
  • 1,071
  • 1
  • 14
  • 30
  • 1
    I think this is probably too broad (what are the differences between), and opinion based (any reason to switch). That said, it's worth noting that **loop** is part of the language, whereas **iterate** is an external library. Remember that Common Lisp was developed to unify a number of different Lisps. Versions of **loop** might have been present in earlier lisps. **iterate** could be designed from the ground up. – Joshua Taylor Nov 16 '15 at 20:41
  • @JoshuaTaylor - I want some practical differences. In my opinion, it's not too broad(as they are rather similar, so there shouldn't be too much difference there), and I'm not asking for reasons to switch that are opinion-based (preference of style), but this is rather backing up sentence for my original question of differences. I mentioned switch because loop is already built in. – MatthewRock Nov 16 '15 at 20:58
  • 7
    Are there specific questions that aren't answered in [the documentation](https://common-lisp.net/project/iterate/), which already begins with "It is similar to the CL:LOOP macro, with these distinguishing marks: ..."? In the manual, there's an appendix called [*Don't Loop, Iterate*](https://common-lisp.net/project/iterate/doc/Don_0027t-Loop-Iterate.html#Don_0027t-Loop-Iterate) that has subsections about comparison between **iterate** and other CL iteration constructs (e.g., dolist, dotimes, etc., and, of course, loop). Section A.3.7 feels like it might answer your questions. – Joshua Taylor Nov 16 '15 at 21:09
  • @JoshuaTaylor And why is this a comment, and not the answer? – MatthewRock Nov 16 '15 at 22:47
  • 1
    Because I don't think it's a suitable answer for suitable Stack Overflow questions. If that's the kind of answer you're looking for, then the question probably falls under a different close reason: "Questions asking us to recommend or find a book, tool, software library, tutorial or other off-site resource are off-topic for Stack Overflow as they tend to attract opinionated answers and spam. Instead, describe the problem and what has been done so far to solve it." – Joshua Taylor Nov 16 '15 at 22:52
  • 2
    Those aren't, by any means, *bad* questions, or *unanswerable* questions, they're just not a great fit for Stack Overflow. It's much harder to get rid of a question once it's got answers with upvotes, so I don't want to post that as an answer. It's just an off-site resource, documentation, that Google can find. – Joshua Taylor Nov 16 '15 at 22:53
  • @JoshuaTaylor I strongly disagree. Here are some answers that could be solved with single Google query, but are top upvoted(meaning that community especially likes these questions): [External + one-liner](http://stackoverflow.com/questions/503093/how-can-i-make-a-redirect-page-using-jquery); [External + tutorial](http://stackoverflow.com/questions/1711631/improve-insert-per-second-performance-of-sqlite); [Reference/google query](http://stackoverflow.com/questions/948135/how-can-i-write-a-switch-statement-in-ruby). – MatthewRock Nov 16 '15 at 23:17
  • I think we are focusing too much on whether the question belongs on SE, and too little on actually helping people by answering questions. SO is Q&A site, meaning that even if your answer would be concise, it is okay to answer here since this site is often used as quick reference for many simple, yet not so common tasks. Plus, the question about difference is by no means opinion based. You can also see looking at your comment that it's not too broad as well. Here is [other question that's not too broad](http://goo.gl/XGRAZi), [second one](http://goo.gl/dquN5h), [third one](http://goo.gl/GCzJf4) – MatthewRock Nov 16 '15 at 23:24
  • 5
    https://items.sjbach.com/211/comparing-loop-and-iterate , other than that the simple answer is: Read The Fine Manual. As Joshua Taylor mentioned, it comes with a LOOP / Iterate comparison. The manual is linked from the Iterate page - see your link. – Rainer Joswig Nov 16 '15 at 23:37

1 Answers1

2

Some things that are unique to iterate:

No rigid order for clauses

loop requires that all for clauses appear before the loop body, for example before while. It's ok for iter:

(iter (for x in '(1 2 99)
  (while (< x 10))
  (for y = (print x))
  (collect (list x y)))

Accumulating clauses can be nested

collect, appending and the like can appear anywhere:

(iter (for x in '(1 2 3))
  (case x
    (1 (collect :a))
    (2 (collect :b))))

finding

;; Finding the longest list in a list of lists:
(iter (for lst in '((a) (b c d) (e f)))
      (finding lst maximizing (length lst)))
=> (B C D)

;; The rough equivalent in LOOP:
(loop with max-lst = nil
      with max-key = 0
      for lst in '((a) (b c d) (e f))
      for key = (length lst)
      do
      (when (> key max-key)
        (setf max-lst lst
              max-key key))
      finally (return max-lst))
=> (B C D)

https://common-lisp.net/project/iterate/ first example

Finding the minimum of x^2 - 4x + 1 in an interval:

(iter (for x from -5 to 5 by 1/100)
      (finding x minimizing (1+ (* x (- x 4)))))
2

©Common Lisp Recipes p.198

next-iteration

it is like "continue" and loop doesn't have it.

iter also has first-iteration-p and (if-first-time then else).

https://web.archive.org/web/20170713081006/https://items.sjbach.com/211/comparing-loop-and-iterate

generators

generate and next. A generator is lazy, it goes to the next value when said explicitly.

(iter (for i in '(1 2 3 4 5))
      (generate c in-string "black")
      (if (oddp i) (next c))
      (format t "~a " c))
b b l l a 
NIL

https://sites.google.com/site/sabraonthehill/loop-v-iter

previous

(iter (for el in '(a b c d e))
      (for prev-el previous el)
      (collect (list el prev-el)))
=> ((A NIL) (B A) (C B) (D C) (E D))

although it is doable with loop's parallel binding and:

(loop for el in '(a b c d e)
      and prev-el = nil then el  
      collect (list el prev-el))

more clauses

in-string

LOOP offers collecting, nconcing, and appending. ITERATE has these and also adjoining, unioning, nunioning, and accumulating.

(iter (for el in '(a b c a d b))
      (adjoining el))
=> (A B C D)

(adjoin is a set operation)

LOOP has summing, counting, maximizing, and minimizing. ITERATE also includes multiplying and reducing. reducing is the generalized reduction builder:

(iter (with dividend = 100)
      (for divisor in '(10 5 2))
      (reducing divisor by #'/ initial-value dividend))
=> 1

https://web.archive.org/web/20170713105315/https://items.sjbach.com/280/extending-the-iterate-macro

It is extensible

(defmacro dividing-by (num &keys (initial-value 0))
  `(reducing ,num by #'/ initial-value ,initial-value))
 
(iter (for i in '(10 5 2))
      (dividing-by i :initial-value 100))
=> 1

but there is more.

https://common-lisp.net/project/iterate/doc/Rolling-Your-Own.html#Rolling-Your-Own

https://web.archive.org/web/20170713105315/https://items.sjbach.com/280/extending-the-iterate-macro where in the Appendix, we see two examples of loop extensions. But they are not portable really, the code is full of #+(or allegro clisp-aloop cmu openmcl sbcl scl) (ansi-loop::add-loop-path …, sb-loop::add-loop-path etc.

Stuff missing in iterate

No parallel binding like loop's and, but not needed?.

I'm probably missing here.


But that's not all, there are more differences.

Ehvince
  • 17,274
  • 7
  • 58
  • 79