Loop structures

From Rosetta Code
Revision as of 16:43, 21 July 2009 by rosettacode>Mwn3d (→‎Visual Basic ?: VB.NET actually. I messed that up long ago. Sorry.)

In this former task, we document loop structures offered by different languages.

Examples here should be migrated to an appropriate Iteration page and removed from here. If a page does not exist demonstrating a particular loop structure, discuss it here.

AppleScript

NOT COVERED IN LOOP PAGES

repeat-until

set i to 5
repeat until i is less than 0
       set i to i - 1
end repeat
repeat
       --endless loop
end repeat

repeat-with

       repeat with i from 1 to 20
               --do something
       end repeat
       set array to {1,2,3,4,5}
       repeat with i in array
               display dialog i
       end repeat

Brainf***

NOT EXPLAINED THIS MUCH IN LOOP PAGES BF's only control flow construct of any kind is a loop. Two of the eight commands define the start and end of a conditional loop.

  • [ - branch forward past matching ']' if the current cell is zero
  • ] - branch back to the matching '[' if the current cell is non-zero

In practice this is equivalent to a "while not zero" loop in other languages.

[-]  set current cell to zero
[->+>+<<]>>[-<<+>>] copy cell 0 to cell 1, using cell 2 as temporary storage

C++

Compile-Time Control Structures

Necessary? A compile-time for loop can be generated with template metaprogramming. Example:

// the loop
template<int start, int finish, template<int n, typename T> class X> struct loop
{
  typedef typename X<start, typename loop<start+1, finish, X>::type>::type type;
};

// the termination of the loop
template<int finish, template<int n, typename T> class X> struct loop<finish, finish, X>
{
  typedef typename X<finish, void>::type type;
};
// example usage: This implements just a very complicated way of building a multi-dimensional array

// the loop body
template<int n, typename T> struct build_array
{
  typedef T type[n];
};

template<int n> struct build_array<n, void>
{
  typedef double type;
};

// the loop execution: This is equivalent to
// typedef double array_type[2][3][4][5];
typedef loop<2,6,build_array>::type array_type;

Clojure

NOT COVERED IN LOOP PAGES

loop

;; loop/recur is the most general looping construct
(loop [lst [1 3 5 7]
       ret []]
   (if lst
       (recur (rest lst) (conj ret (* (first lst) (first lst))))
       ret))
==> [1 9 25 49]

Factor

NOT COVERED IN LOOP PAGES

Looping

Most looping is done with recursion. Tail recursion is properly optimized.

   : forever ( quot -- ) dup slip forever ; inline
   [ "A hungry raptor stalks you..." print flush 2000 random sleep ] forever

Iteration

Most indices are implicit or not present at all.

   3 [ "pint" drink ] times
   { "high" "level" "language" } [ print ] each
       high
       level
       language
   10 [ sq ] map
       { 0 1 4 9 16 25 36 49 64 81 }
   { 1 2 3 } { 4 5 6 } [ * ] 2map .
       { 4 10 18 }
   10 [ even? ] subset .
       V{ 0 2 4 6 8 }
   0 10 3 <range> >array .
       { 0 3 6 9 }
   10 1 -2 <range> >array .
       { 10 8 6 4 2 }
   2222 [ dup 0 > ] [ 2/ dup ] [ ] unfold nip .
       { 1111 555 277 138 69 34 17 8 4 2 1 0 }

Iterating with an index:

   : indexed-alphabet. ( -- )
       "abcdefghijklmnopqrstuvwxyz"
       [ [ 1string ] [ number>string ] bi* ": " glue print ] each-index ;

Forth

DO-LOOP

( limit start ) DO ( iterated statements ) LOOP
( limit start ) DO ( iterated statements ) ( increment ) +LOOP
LEAVE \ exits a DO loop
UNLOOP EXIT \ cleans up loop counters from return stack before returning from the current word

example: Two standard iterations

10 0 DO I . LOOP      \ Prints the numbers from 0 to 9
10 0 DO I . 2 +LOOP   \ Prints the even numbers from 0 to 8

BEGIN-UNTIL

BEGIN ( iterated statements ) ( conditional ) UNTIL

example: Counts down from a given number to zero

: COUNTDOWN ( n -- )  BEGIN  DUP CR .  1- DUP 0< UNTIL  DROP ;

BEGIN-AGAIN

BEGIN ( iterated statements ) AGAIN

example: echo user's input

: FOREVER ( -- )   BEGIN  KEY EMIT  AGAIN ;

BEGIN-WHILE-REPEAT

BEGIN  ( conditional ) WHILE  ( iterated statements )  REPEAT

example: counts down from a given number to one

: COUNTDOWN ( n -- )  BEGIN  DUP WHILE  CR DUP . 1-  REPEAT  DROP ;

Additional WHILE clauses may be added to a loop, but each extra WHILE requires a matching THEN after the REPEAT.

Mixed Structures

Because Forth's compiler is laid bare to the programmer, it is quite easy to both define your own looping structures or combine existing structures in interesting ways. The rules for such combining are somewhat involved, though discussions can be found in the gforth user's manual, among other places. These more complex looping constructs can make up for Forth's lack of a "break" word, and can allow expressing complex loops without resorting to boolean variables. A practical example is also found in the Binary search task.

A good example of a useful combination is this complex loop:

BEGIN
  ( condition 1 )
WHILE
  ( condition 2 )
UNTIL
  ( condition 2 succeeded )
ELSE
  ( condition 1 failed )
THEN

An example of using this idiom in practice might be this pseudo-Forth

BEGIN
  read-next-record
WHILE
  found-record
UNTIL
  process-record
ELSE
  error" Ran out of records looking for the right one!"
THEN


Groovy

While Loops

while (true) {
  println 'groovy'
}

For Loops


 // iterate over a range
 x = 0
 for (i in 1..3) { x += i }
 assert x == 6

 // iterate over a list
 x = 0
 for (i in [1, 2, 3]) { x += i }
 assert x == 6

 // iterate over an array
 x = 0
 for (i in (1..3).toArray()) { x += i }
 assert x == 6

 // iterate over a map's key/value pairs
 x = 0
 for (i in map) { x += i.value }
 assert x = 6

 // iterate over a map's values
 x = 0
 for (i in map.values()) { x += i }
 assert x == 6

 // iterate over the characters in a string
 text = 'abc'
 list = []
 for (c in text) { list.add(c) }
 assert list == ['a', 'b', 'c']

Each

 def stringList = [ "java", "perl", "python", "ruby" ];

 def stringMap = [ "Su" : "Sunday", "Mo" : "Monday", "Tu" : "Tuesday",
                  "We" : "Wednesday", "Th" : "Thursday", "Fr" : "Friday",
                  "Sa" : "Saturday" ];

 stringList.each() { print " ${it}" }; println "";
 // java perl python ruby

 stringMap.each() { key, value -> println "${key} == ${value}" };
 // Su == Sunday
 // We == Wednesday
 // Mo == Monday
 // Sa == Saturday
 // Th == Thursday
 // Tu == Tuesday
 // Fr == Friday  

 stringList.eachWithIndex() { obj, i -> println " ${i}: ${obj}" };
 // 0: java
 // 1: perl
 // 2: python
 // 3: ruby

 stringMap.eachWithIndex() { obj, i -> println " ${i}: ${obj}" };
 // 0: Su=Sunday
 // 1: We=Wednesday
 // 2: Mo=Monday
 // 3: Sa=Saturday
 // 4: Th=Thursday
 // 5: Tu=Tuesday
 // 6: Fr=Friday

Haskell

Most of the usual applications for loops are realized in Haskell by operations on (lazy) lists, like map, fold or filter. It's unusual to use loops in an imperative style. However, if one insists on it, it's easy to make your own implementation of any loop variant.

Here are a few examples:

Pre-checked loop (while)

whileM :: Monad m => m Bool -> m a -> m ()
whileM cond body = 
  cond >>= \b -> if b then body >> untilM cond body else return ()

Post-checked loop (repeat-until)

untilM :: Monad m => m Bool -> m a -> m ()
untilM cond body = 
  body >> cond >>= \b -> if b then return () else untilM cond body

For-style loop

Simplest done by iterating over a list:

forM :: Monad m => [a] -> (a -> m ()) -> m ()
forM []     f = return ()
forM (x:xs) f = f x >> forM xs f

IDL

It should be noted that IDL programmers tend to avoid loops -- most of the time loops are used to access the elements of arrays or vectors, and since IDL is an array language the same purpose can almost always be served in a faster, more elegant and more readable way though any of the array operations.

for

 for i=0,50,2 do print,i

prints out every second number starting at 0 stopping at 50. Wherever a single command can go in IDL, there can always go a begin...end pair with arbitrary amount of code in between. Thus the above can also read

 for variable = start, stop [,increment] do begin
   ;some code here
   ;some more code
 endfor

It is allowed but not required to use the appropriate "type of end" - i.e. it would be allowed to just say "end" instead of "endfor". However "endfor" (and "endwhile", "endif" etc) will throw an error if the wrong one is encountered at compile time and thus it is recommended to always use the more descriptive form since it makes debugging a lot easier.

while

 while condition do command

Same extensions as above:

 while running do begin
   ; various snippets of code that might change the variable 
   ; "running" from something true to something false
 end[while]

repeat

 repeat command until condition

etc

goto

'Goto' exists and can in principle be forced to make a loop:

 label: 
   ;some code
 [if condition then $]
 goto label

break

The break statement will immediately terminate the current innermost for, while, repeat, if, case or switch without having to resort to a goto.


forever [right random 360 forward 10]
repeat 5 [right 180-36 forward 100]

Repeat and forever also have access to a loop counter, starting at 1.

repeat 10 [print repcount]
while [:x > 0] [make "x :x / 2]
do.while [make "x :x / 2] [:x > 0]
until [:x = 0] [make "x :x / 2]
do.until [make "x :x / 2] [:x = 0]

LSE64

LSE's loop words all work via tail recursion, like Scheme, by re-executing the current word. If used interactively, "repeat" works upon the current line. Exiting words, like "&&", "||", and "exit" can be used to exit an otherwise infinite loop (see other tasks).

infinite : " again and " ,t repeat
limited : continue? &repeat

Counted loops execute a specified word n times. Within that word, "count" accesses a loop counter, counted down to zero.

body : count , sp
10 body iterate    # 10 9 8 7 6 5 4 3 2 1 

body? : count , sp  count 5 >
10 body? &iterate   # 10 9 8 7 6 5

Make

Make does looping through recursion.
SUCC=`expr $* + 1`
MAX=10

all: 0-n;

%-n: %-echo
   @-make -f loop.mk $(SUCC)-n MAX=$(MAX)

%-echo:
   @echo $*

$(MAX)-n: $(MAX)-echo;

Invoking it

|make -f loop.mk MAX=2
0
1
2

newLISP

Works with: newLISP version v.9.0

dotimes

(dotimes (x 10) (println (+ x 1)))

do-until

(set 'x 1)
(do-until (= x 10) (inc 'x) (println x))

do-while

(set 'x 1)
(do-while (< x 10) (inc 'x) (println x))

for

(for (x 1 10) (println x))

OCaml

for

<lang ocaml># for i = 0 to 4 do

   Printf.printf "%d\n" i;
 done;;

0 1 2 3 4 - : unit = ()</lang>

for down to

<lang ocaml># for i=4 downto 0 do

   Printf.printf "%d\n" i;
 done;;

4 3 2 1 0 - : unit = ()</lang>

while

<lang ocaml># let line = ref "" in

 while !line <> "exit" do
   line := input_line stdin;
   print_endline(String.uppercase !line);
 done;;        

objective caml OBJECTIVE CAML exit EXIT - : unit = ()</lang>

let rec

The for and while loops are imperative features of OCaml, and most often it is rather recommended to prefer using functional loop designed with recursive functions, or better when iterating over a list or an array using a built-in iterator from the standard library or the extLib library. <lang ocaml>let rec loop i =

 Printf.printf "%d\n" i;
 if i <= 4 then loop (i + 1)

in loop 0</lang>

Built-in Iterators

<lang ocaml>List.iter List.fold_left Array.iter Array.iteri</lang>

Pascal

while

Works with: Turbo Pascal version 7.0
 WHILE condition1 DO
   BEGIN
     procedure1;
     procedure2;
   END;

repeat-until

Works with: Turbo Pascal version 7.0
 REPEAT
   procedure1;
   procedure2;
 UNTIL condition1;

for

Works with: Turbo Pascal version 7.0
 FOR counter := 1 TO 10 DO
   BEGIN
     procedure1;
     procedure2;
   END;
Works with: Delphi version 1.x+
 Var
  Counter : char ;
 FOR counter := 'A' TO 'Z' DO
   BEGIN
     procedure1;
     procedure2;
   END;

Pop11

while

Pop11 offers multiple looping constructs. Basic one is while loop:

 5 -> n;
 while n > 0 do 
     printf(n, '%p\n');
     n - 1 -> n;
 endwhile;

until

Variant of while is until loop:

until condition do /* Action */ enduntil;

is equivalent to:

while mot(condition) do /* Action */ endwhile;

for

One can process all elements of a list:

 for x in [a b c] do x => endfor;

It is possible to simultaneously process multiple lists:

for x y in [a b c], [1 2 3] do [^x ^y] => endfor;

in first iteration sets x to "a" and y to 1, in the second x is "b" and y is 2, in the third (last) iteration x is "c" and y is 3. The iteration ends when the shortest list is exhausted.

Sometimes one wants to process tails of the list, to do this use on keyword instead of in keyword:

for x on [a b c] do x => endfor;

in first iteration sets x to [a b c], in the second to [b c], etc...

There is also "counting" version of for loop:

for x from 2 by 2 to 7 do x => endfor;

goes trough 2, 4 and 6. Ommited by frase means by 1.

There is alse a C-like for loop:

for action1 step  action2 till condition do /* Actions */ endfor;

is equivalent to

action1
while not(condition) do
   /* Actions */
   action2
endwhile;

There are more specialized kinds of loops, but we skip them here.

quitloop quitif quitunless

Inside loops one can use control transfers to prematurely exit the loop or end current iteration and start the next one:

while true do n - 1 -> n; quitif(n=0); endwhile;

quits loop when n=0. quitloop unconditionally quits loop, quitunless(x) is equivalent to quitif(not(x)).

nextloop nextif nextunless

Similarely to quitloop nextloop unconditionally ends current iteration and starts the new one, nextif(x) ends current iteration when x is true, nextunless(x) is equivalent to nextif(not(x)). The loop control transfers can be also used inside for (and until) loops.

Finally, it is frequently possible to avoid explicit iteration using higher order map functions (like appdata and mapdata).

PostScript

The "for" operator expects three numbers and a procedure on the stack. It will consume all four arguments then it will push the first number on the stack, execute the procedure, increase the first number by the second number, push it on the stack, execute the procedure etc until the third number is reached. For example

10 12 200 
  {dup moveto 100 0 lineto} 
  for 
stroke

will add lines to the currentpath that start at coordinates {10,10}; {22,22}; {34,34} ... and all end at {100,0}. The "stroke" operator then renders these lines on the current output device (usually a screen or a piece of paper).

Python

for

Typically for is used to iterate over items in an iterable. Most Python built-in objects support iteration: lists, tuples, strings (including unicode string objects), dictionaries (by keys), sets, ranges (including the results from calls to the xrange() built-in functions) and files (line by line). Any object can support iteration by adding special methods.

<lang python>

for x in ["foo", "bar", "baz"]:
    print x

</lang>

Frequently one wants to both iterate over a list and increment a counter:

<lang python>

mylist = ["foo", "bar", "baz"]
for i, x in enumerate(mylist):
    print "Element no.", i, " is", x

</lang>

Iterating over more than one list is achieved by zip:

<lang python>

for x, y, z in zip(lst1, lst2, lst3):
    print x, y, z

</lang>

Iterating over more than one list + incrementing a counter:

<lang python>

for counter, [x, y, z] in enumerate(zip(lst1, lst2, lst3)):
    print counter, x, y, z

</lang>


The built-in range() and xrange() functions are commonly used to provide indexes over which to iterate. range() returns a list while xrange() returns a generator object without building the list in memory:

<lang python>

import sys
for i in xrange(sys.maxint):
    print i, 

</lang>

This would usually result in a MemoryError if we attempted to use the range() because it would try to create a list in memory consisting of all the integers from 0 up to the system's maximum. However, with xrange() this will run without error (for a very long time or until it's interrupted).

Optional else suite is executed unless break was called during iteration:

<lang python>

for i in numbers:
    if item < 0:
        break
else:
    print 'all numbers are positive'

</lang>

Because of the pervasive support for iteration and generators in Python classes and libraries the for loop structure is far more commonly used than while.

list comprehension expressions

Typically used when you want to create a list and there is little logic involved. Faster than for loop:

positives = [n for n in numbers if n > 0]

A list comprehension is an expression rather than a statement. This allows them to be used as arguments to a function:

<lang python>

  def square_each(n):
      results = []
      for each in n:
         results.append(each * each)
      return results
  squares_3x5 = square_each([x for x in range(100) if (x%3)==0 and (x%5)==0])
  # Return a list of all the squares of numbers from 1 up to 100 those numbers are
  # multiples of both 3 and 5.

</lang>

while

Typical use:

<lang python>

while True:
    # Do stuff...
    if condition:
        break

</lang>

You can add optional else, which is executed only if the expression tested was false. Typically used for searches.

<lang python>

while True:
    # Do stuff...
    if found:
        results = ...
        break
else:
   print 'Not found'

</lang>

Since Python has no "bottom-tested" loop construct (such as "do ... until") ... it's common Python practice to either rethink the design in terms of iteration or to use an while 1 (infinite loop) and break out of it as appropriate.

Raven

each

10 each as i                                     # counted loop
    "index is %(i)d\n" print

'hello world' each as c                          # string characters
    "%(c)c" print

[ 'a' 'b' 'c' ] each as item                     # list items
    "%(item)s" print

{ 'a' 1 'b' 2 } each pair as k, v                # hash key/val pairs
    "%(k)s => %(v)d\n" print

'SELECT * FROM table' mysql query each as row    # iterable resource 
    row print

repeat while/until

repeat <some_condition> while
    <some_process>

repeat <come_condition> until
    <some_process>

Seed7

In Seed7 new statements can be declared easily. This feature is not explained here. Here are examples of the predefined loops:

while

while TRUE do
  foo;
end while;

repeat

repeat
  foo;
until FALSE;

for

for i range 0 to 4 do
  foo;
end for;
for i range 4 downto 0 do
  foo;
end for;
for stri range []("foo", "bar", "baz") do
  writeln(stri);
end for;

Smalltalk

timesRepeat

 10 timesRepeat: [ expression ].

iterating over a collection

 ( collection ) do: [ expression ].
 ( collection ) collect: [:element | element sendMessageToElement].
 #(1 2 3 4) inject: 5 into: [:sum :number | sum + number]

whileTrue/whileFalse

 x := 0.
 [ x < 100 ]
      whileTrue: [ x := x + 10.].
 [ x = 0 ]
      whileFalse: [ x := x - 20.].

simple looping

 1 to: 5 do: [:number | Transcript show: 'Here is a number: ' number printString ; cr]
 (-50 to: 50 by: 4) do: [:number | Transcript show: number ; cr]

SNUSP

==in==!/==body==?\==out==
       \==ydob===/

The basic loop structure can be modified in many ways. You can have a pre-loop test by including ? before the loop.

A unique feature of SNUSP is the ability to write bi-directional loops, designed for different effect depending on which direction the flow of control is running around the loop. The two entry points into this subroutine will move a value either up or down one cell, determined by the direction the loop is circulating.

         #    #
up1====?!/->+<\
         ?    ?
down1==?!\<+>-/
         #    #


Toka

countedLoop

Counts up or down until the boundaries are met.

10 0 [ i . ] countedLoop
0 10 [ i . ] countedLoop

whileTrue

Repeatedly executes a quote until the quote returns true.

100 [ dup . 1 - dup 0 <> ] whileTrue

whileFalse

Repeatedly executes a quote until the quote returns true.

0 [ dup . 1 + dup 101 = ] whileFalse

Visual Basic .NET

Do/Loop

   Sub InfiniteLoop()
       Do
           'code
       Loop
   End Sub

   Sub LoopWithInnerCondition()
       Do
           'code
           If Condition() Then Exit Do
           'more code
       Loop
   End Sub

   Sub PreConditionLoop1()
       Do While Condition() 'loop continues while Condition is true
           'code
       Loop
   End Sub

   Sub PreConditionLoop2()
       Do Until Condition() 'loop continues until Condition is true
           'code
       Loop
   End Sub

   Sub PostConditionLoop1()
       Do
           'code
       Loop While Condition() 'loop continues while Condition is true
   End Sub

   Sub PostConditionLoop2()
       Do
           'code
       Loop Until Condition() 'loop continues until Condition is true
   End Sub

   Sub ClassicLoop() 'not generally used
       While Condition() 'loop continues while Condition is true
           'code
       End While
   End Sub

For

  • The type of the iterator variable (i in these example) is infered from the upper and lower bounds.
  • If a Step clause isn't provided, it is assumed to be 1.
  • Loops can be left early using Exit For
  • The upper bound is inclusive.
   Sub ForLoop1()
       For i = 1 To 10
           'code
       Next
   End Sub

   Sub ForLoop2() 'skips even numbers
       For i = 1 To 10 Step 2
           'code
       Next
   End Sub

   Sub ForLoop3() 'iterates backwards
       For i = 10 To 1 Step -1
           'code
       Next
   End Sub

For Each

   Sub ForEachLoop() 'iterates over a collection
       For Each item In Source()
           'code
       Next
   End Sub

   Function ForEachLoop2() 'searching for a string, exiting early if found
       Dim found As Boolean
       For Each item In Source()
           If item = "CAR" Then
               found = True
               Exit For
           End If
       Next
   End Function