title:: Iteration
summary:: for, do, loop, repeat
categories:: Core,Common methods
related::  Classes/Object, Classes/Function, Classes/Routine, Classes/Stream, Classes/Pattern


(This page combines material formerly in the Control Structures and loop/repeat helpfiles.)

There are a number of ways to implement iteration in SuperCollider.
The most familiar ones will be the link::Classes/Number#-for:: and link::Classes/Collection#-do:: methods.
The link::Classes/Function#-while:: method is discussed link::Reference/Conditional-Execution#while#here::.

For Routines (Streams) and Patterns, special methods exist: link::#Patterns and
Routines: repeat and loop#.repeat and .loop::

table::
	## strong::Thing you want to do:: ||  strong::method to use:: || strong:: returns::
	## iterate over a numeric range  || link::#for::, link::#forBy:: || code::loopFunc.value(n):: for each number code::n:: in range
	## iterate over integers from math::0:: to math::n-1:: || link::#do#n.do:: || code::loopFunc.value(i):: for each integer code::i:: between math::0:: and math::n-1:: inclusive.
	## iterate over a collection  	|| link::#do#collection.do:: 	|| code::loopFunc.value(x):: for each element code::x:: of collection
	## iterate while some condition is true || link::Reference/Conditional-Execution#while:: || code::loopFunc.value:: for each iteration.
	## embed in a stream n times || link::#.repeat::(n) (with argument) || link::Classes/Routine:: or link::Classes/Pn::
	## embed in a stream an infinite number of times || link::#Apart from Function.loop, the .loop method is an alias for .repeat(inf)#.loop::|| a link::Classes/Routine:: or link::Classes/Pn::
	## link::#Breaking from a loop#break from a loop:: || link::Classes/Function#-block:: || teletype::nil:: unless specified; see link::#Breaking from a loop#below::
::

section:: for, forBy, do

subsection:: for

The for message implements iteration over an integer series from a starting value to an end value stepping by one each time.
A function is evaluated each iteration and is passed the iterated numeric value as an argument.

Syntax

code::
for(startValue, endValue) { loopFuncBody }

// alternate
for(startValue, endValue, loopFunc)

Example
code::
for(3, 7) { arg i; i.postln };  // prints values 3 through 7
::

subsection:: forBy

The forBy selector implements iteration over an integer series with a variable step size.
A function is evaluated each iteration and is passed the iterated numeric value as an argument.

Syntax
code::
forBy(startValue, endValue, stepValue) { loopFuncBody };

forBy(startValue, endValue, stepValue, loopFunc);
::

Example
code::
forBy(0, 8, 2) { arg i; i.postln };  // prints values 0 through 8 by 2's
::


subsection:: do

Do is used to iterate over a link::Classes/Collection::.
Positive Integers also respond to code::do:: by iterating from zero up to their value (excluding that value).
Collections iterate, calling the function for each object they contain.
Other kinds of Objects respond to do by passing themselves to the function one time.
The function is called with two arguments, the item, and an iteration counter.

Syntax
code::
collection.do { loopFuncBody };

// alternate
collection.do(loopFunc)

// alternates, rarely seen
do(collection, loopFunc)
do(collection) { loopFuncBody };
::

Example
code::
[ 1, 2, "abc", (3@4) ].do { arg item, i; [i, item].postln; };

5.do { arg item; item.postln }; // iterates from zero to four

"you".do { arg item; item.postln }; // a String is a collection of characters

'they'.do { arg item; item.postln }; // a Symbol is a singular item

(8..20).do { arg item; item.postln }; // iterates from eight to twenty

(8,10..20).do { arg item; item.postln }; // iterates from eight to twenty, with stepsize two

Routine {
	var i = 10;
	while { i > 0 } {
		i.yield;
		i = i - 5.0.rand
	}
}.do { arg item; item.postln };  // 'do' applies to the Routine
::

Note:: The syntax code::(8..20).do:: uses an optimization to avoid generating an array that is used only for iteration (but which would be discarded thereafter).
The return value of code:: (8..20).do { |item| item.postln } :: is 8, the starting value.

However, if code::do:: is written as an infix binary operator, as in code::(8..20) do: { |item| item.postln }::, then it will generate the series as an array first, before calling Array:do.
One side effect of this is that it is valid to code::do:: over an infinite series within a routine only if code::do:: is written as a method call.
If it is written as a binary operator, you will get a "wrong type" error because the array must be finite.

code::
// OK: 'do' is a method call
r = Routine {
	(8 .. ).do { |i|
		i.yield;
	};
};

r.next;
-> 8
-> 9 etc.

// ERROR: 'do' is an operator
r = Routine {
	(8 .. ) do: { |i|
		i.yield;
	};
};

r.next;

ERROR: Primitive '_SimpleNumberSeries' failed.
Wrong type.
::
::

section:: Breaking from a loop

To break from a loop, use the link:: Classes/Function#-block:: method.

The syntax is somewhat unusual.
Consider the following loop:
code::
100.do { |i| i.postln; }
::
Suppose we want the loop to stop after code:: i == 7::.
Other languages (e.g. javascript or python) would allow us to write expressions analogous to the following:

code::
// this won't work in SC
100.do { |i| if(i == 7) {break}; i.postln; } // syntax error;
::
However, there is no break keyword in sclang;
instead, we have to do three things (not in order, but simultaneously):

numberedlist::
## enclose the looping expression (code::100.do { ... }:: here) in another Function block that takes an argument
(which we call teletype::break:: here, but which can be called anything);

code:: 
{ |break|   
	100.do { |i|  // the original expression
	i.postln;     // from which we 
	}             // want to break.
} 
::

## inside the looped Function, call code::.value:: on that argument when the relevant condition is true;

code:: 
{ |break|  
	100.do { |i| 
	i.postln; 
	if (i == 7) {   // added lines
		break.value // ...
		}           // ...
	} 
} 
::

##  on the enclosing Function, call  code::.block.::

code:: 
block { |break| // block goes at the beginning of this line
		100.do { |i| 
				i.postln; 
				if (i == 7) {
					break.value
					} 
		} 
} 
// this is the complete expression, at last
::
::

This will return nil once the break condition is reached,
but if a specific return value is desired, this can be provided to the code::.value:: call:

code:: 
block { |break| 
		100.do { |i| 
				i.postln; 
				if (i == 7) {
					break.value("return this")
					} 
		} 
} 
//phew
::

section:: There is no continue keyword in SuperCollider

Some languages permit "skipping" individual iterations of a loop by means of a "continue" keyword.
For instance, in python, the following will print teletype::0,1,2,  4,5,6,7,8,9::,
skipping over the teletype::3:::

teletype::
# this is python, not sclang
for i in range(10):
	if i == 3:
		continue
	print(i)
::

Note that the remainder of the body of the loop, teletype::print(i)::, is fully skipped over when the continue keyword is reached.
For the same result in sclang, the body of the loop must be moved emphasis::inside:: the conditional statement:
code::
10.do { |i|
	if (i == 3) {
		//no code here.
	} {
		i.postln; // the equivalent to print(i) above
	}
}
// the above code is awkward, it merely serves an explanatory purpose.
// more elegant in pratice is to negate the continue condition:
10.do { |i|
	if (i != 3) {
		i.postln;
	}
}
::

section:: Patterns and Routines: repeat and loop

The method code::.repeat(n):: can be used to create a Routine or a Pattern which repeats values for a specific number of times.
To repeat indefinitely, use either code::.loop::, or use code::.repeat:: without supplying an argument.

Roughly, if teletype::pat:: is some Pattern, then code::pat.repeat(n):: will return code::Pn(pat, n)::.
For most other classes, code::object.repeat(n):: will return a Routine equivalent to code::Pn(object, n).asStream::.

Regarding code::Function.loop::, which should only be used strong::inside:: a Routine, 
see link::#Apart from Function.loop, the .loop method is an alias for .repeat(inf)#below::.

subsection:: .repeat

definitionlist::
## link::Classes/Object#-repeat::(n) ||
	Returns a Routine.

 	Embeds the receiver n times by wrapping it in a link::Classes/Pn:: and calling link::Classes/Pattern#-.asStream:: on it.
	If no argument is provided, the stream will repeat indefinitely.

	Implementation:
	code:: repeat { arg n = inf; ^Pn(this, n).asStream } ::

	Example:

code::
	x = [0,1,2]; // an Array
	y = x.repeat(4); // a Routine that repeats the array 4 times
	y.nextN(15); // -> [[0,1,2],[0,1,2],[0,1,2],[0,1,2],nil,nil,nil,nil,nil,nil,nil]
::

## link::Classes/Pattern#-repeat::(n) ||
	Returns a link::Classes/Pn::.

	Embeds the receiver n times by wrapping it in a link::Classes/Pn::, but doesn't call code::.asStream:: on it.
	link::Classes/Pattern#-repeat#pattern.repeat(n):: is thus effectively a synonym for link::Classes/Pn##Pn(pattern, n)::.
	If no argument is provided, the Pattern will repeat indefinitely.

Example:
code::
	// x is a pattern that counts from 0 to 2
	x = Pseq([0,1,2]); // -> a Pseq
	// y is a pattern that does this 4 times in a row
	y = x.repeat(4); // -> a Pn
	y.asStream.nextN(15); // -> [0,1,2,0,1,2,0,1,2,0,1,2,nil,nil,nil]
::

## link::Classes/Routine#-repeat::(n) ||

	Embeds the receiver in another Routine that repeats it n times, and returns that.
	For instance:

code::
	// x is a a Routine that counts from 0 to 2
	x = Routine({ 3.do({ arg i; i.yield }) }); // -> a Routine
	// y is a Routine that does x four times
	y = x.repeat(4); // -> a Routine
	y.nextN(15); // -> [0,1,2,0,1,2,0,1,2,0,1,2,nil,nil,nil]
::
::

subsection:: Apart from Function.loop, the .loop method is an alias for .repeat(inf)

code::.loop:: is simply an alias for code::.repeat(inf)::.
An important exception to this is link::Classes/Function#-.loop::,
which should be treated with care:

definitionlist::

## link::Classes/Function#-loop:: ||
	Used on a function Emphasis::inside:: a link::Classes/Routine::,
	it will result in a Routine that repeats the receiver function an infinite number of times.
	Used on a Function emphasis::outside:: a Routine, it will crash the interpreter.

	Example:
code::
	f = { 3.yield; }; // -> a Function
	x = Routine({ f.loop }); // -> a Routine
	10.do({ x.next.postln }); // -> [3,3,3,3,3,3,3,3,3,3]
	// Similar outcome:
	x = Routine(f).loop; // -> a Routine
	10.do({ x.next.postln }); // -> [3,3,3,3,3,3,3,3,3,3]
::
::
