OpenSCAD User Manual/Flow Of Control Statements
For() Module
A module that will invoke its child module(s) repeatedly.
Format
for( <loop_var> ) <child expression>;
As with any module, the child of a for()
may be a block of code in braces:
for( <loop_var> ) { one(); two(); x=12 };
Parameters
- <loop_vars>
- the loop variable determines how many times the <child expression> will be invoked. It is also a local variable in the scope of the <child expression>.
- <child expression>
- the loop will invoke this expression once for each value of the loop variable. It may be a statement, module call, or a block of statements in braces.
Loop Variable Formats
A for() loop must operate a fixed number of times as set by the loop variable. There are a number of formats for specifying the value that the loop variable will have in each iteration.
- Range
- for( r=[start:incr:end] ), 'r' will be a number in the sequence of the range.
for( r= [start : end] ) - Vector
- for( v = [vector] ), 'v' will be elements of the vector and so may be of any data type, or an unnamed function (a lambda function).
- String
- for( s = "string" ), 's' will be a single letter string
- Object
- for( o = object ), 'o' will be a string containing the name of a member of the object, in the order members were defined in.
Note: Loop variables for an object are only indirect references to the content of its members, unlike the other types. To access the members of an object the String-Index form may be used, member=object[o]
Range Examples
The normal way to use a range:
for (a =[3:5])echo(a); // 3 4 5
Counting down using a range [Deprecated: start > end is deprecated after 2015.03 and will be removedin a future release. Use negative increment instead]
for (a =[3:0]){echo(a);} // 0 1 2 3 for (a =[3:-1:0]){echo(a);} // negative increment : 0 1 2 3
Note: The End must be less than start when increment is less than zero
Counting by fractions
for (a =[3.0 :0.5: 5.0])echo(a); // 3 3.5 4 4.5 5
Loop will stop when current_value + Increment > end
so the end value may not be reached
for (a =[0:2:5])echo(a); // 0 2 4 : a + 2 > 4 stops the loop
Vector Examples
The loop value is defined with each element of the vector in order:
for (a =[3,4,1,5]) echo(a); // 3 4 1 5
It will be whatever data type the element is
for (a =[[1,2],6,"s",[[3,4],[5,6]]]) echo(a); // [1,2] 6 "s" [[3,4],[5,6]]
Object Examples
[Note: Requires version Development snapshot]
The loop value is defined with the name of each member of the object, in the order they were defined in.
thing = object( this="str", that=12 ); for( o=thing ) echo( o, thing[o] );
shows:
ECHO: "this", "str" ECHO: "that", 12
There are built-in functions that return objects:
tm = textmetrics("Hello, World!"); for (name = tm) echo(name, tm[name]);
For is a Module
The for() is a module that invokes its child module repeatedly. The loop variable(s) are local to the scope of the for() and are defined separately in each branch of a tree of instances.
Hence:
for (i=[0:3]) translate([i*10,0,0]) cube(i+1);
Using menu Design > Display-CSG-Tree
shows how the loop is unrolled and the variables are given fixed values in each instance:
group() { multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { cube(size = [1, 1, 1], center = false); } multmatrix([[1, 0, 0, 10], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { cube(size = [2, 2, 2], center = false); } multmatrix([[1, 0, 0, 20], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { cube(size = [3, 3, 3], center = false); } multmatrix([[1, 0, 0, 30], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { cube(size = [4, 4, 4], center = false); } }
Thus the for() is replaced by a group() containing a sequence of four instances of multmatrix() ( for the translate() ) that each have a child cube().
Very different from the way a procedural language would have one block of code that would be executed four times.
Nested for()
While it is reasonable to nest multiple for() statements such as:
for(z=[-180:45:+180]) for(x=[10:5:50]) rotate([0,0,z]) translate([x,0,0]) cube(1);
instead, all ranges/vectors can be included in the same for() operator.
for ( variable1 = <range or vector> , variable2 = <range or vector> ) <do something using both variables>

example for() nested 3 deep color_vec = ["black","red","blue","green","pink","purple"]; for (x = [-20:10:20] ) for (y = [0:4] )color(color_vec[y]) for (z = [0,4,10] ) {translate([x,y*5-10,z])cube();} shorthand nesting for same result color_vec = ["black","red","blue","green","pink","purple"]; for (x = [-20:10:20], y = [0:4], z = [0,4,10] ) translate([x,y*5-10,z]){color(color_vec[y])cube();}
- Examples using vector of vectors

example 1 - iteration over a vector of vectors (rotation) for(i = [ [ 0, 0, 0], [ 10, 20, 300], [200, 40, 57], [ 20, 88, 57] ]) { rotate(i) cube([100, 20, 20], center = true); }

example 2 - iteration over a vector of vectors (translation) for(i = [ [ 0, 0, 0], [10, 12, 10], [20, 24, 20], [30, 36, 30], [20, 48, 40], [10, 60, 50] ]) { translate(i) cube([50, 15, 10], center = true); }

example 3 - iteration over a vector of vectors for(i = [ [[ 0, 0, 0], 20], [[10, 12, 10], 50], [[20, 24, 20], 70], [[30, 36, 30], 10], [[20, 48, 40], 30], [[10, 60, 50], 40] ]) { translate([i[0][0], 2*i[0][1], 0]) cube([10, 15, i[1]]); }
Intersection For Loop
Iterate over the values in a range or vector and create the intersection of objects created by each pass.
Besides creating separate instances for each pass, the standard for() also groups all these instances creating an implicit union. intersection_for() is a work around because the implicit union prevents getting the expected results using a combination of the standard for() and intersection() statements.
intersection_for() uses the same parameters, and works the same as a For Loop, other than replacing the implicit union with an intersection.
example 1 - loop over a range: | ||
intersection_for(n = [1 : 6])
{
rotate([0, 0, n * 60])
{
translate([5,0,0])
sphere(r=12);
}
}
|
![]() |
![]() |
example 2 - rotation : | ||
intersection_for(i = [ [ 0, 0, 0],
[ 10, 20, 300],
[200, 40, 57],
[ 20, 88, 57] ])
{
rotate(i)
cube([100, 20, 20], center = true);
}
|
![]() |
![]() |
If Statement
A module that evaluates an expression as a boolean value and then selects which of its children to invoke. The first child is written normally following the if() with the optional second child following the keyword "else".
if (test) doWhenTrue if (test) doWhenTrue else doWhenFalse
As with any module, the child of an if()
, or of an else
, may be a block of statements in braces:
if (test) { one(); two(); x=12 } if (test) {some=4;thing=5} else {some="a";thing="b";else="c"}
which may be empty to act as placeholders:
if (a==4) {} else echo("a is not 4");
- Parameters
- test: Usually a boolean expression, but can be any value or variable.
- See here for true or false state of values.
- See here for boolean and logical operators
- Do not confuse the assignment operator '=' with the equal operator '=='
- doWhenTrue: expression to perform when true.
- doWhenFalse: expression to perform when false.
- test: Usually a boolean expression, but can be any value or variable.
expression | Description |
---|---|
b==a | true when values match |
a<b | true when a is less than b |
a&&b | true when both a and b are true |
(a>=5)&&(a<=8) | a is within the range 5-8 |
Functional Examples
if( true )
cube(4);
if( false)
sphere(5);
else
cube(5);
The code generated is shown by doing Design > Display CSG Tree...
group() {
cube(size = [4, 4, 4], center = false);
}
group() {
cube(size = [5, 5, 5], center = false);
}
Note that code is only generated for the parts of an if() for which the test is true
.
If the true value in the first if() was changed to false there would be nothing in the model's tree from that statement.
If Else as Switch
Other languages may have a way to select between a number of actions based on a selector variable:
if(test=="a") {scope1} else if(test=="b") {scope2} else if(test=="c") {scope3} else if(test=="d") {scope4} else {scope5} // default action when test is out of range "a":"d"
Code will be generated only for the statements in the selected scope. Of course, the conditional test may be any expression:
if( (k>8)&&(k<100) ) cube(10); else if(y==6) {sphere(6);cube(10);} else echo("any other condition");
Conditional ?: Operator
A ternary function that uses a test to determine which of 2 expressions to do.
a = test ? doWhenTrue : doWhenFalse; echo( test ? doWhenTrue : doWhenFalse);
It works like the ?: operator in other languages like 'C' or Java.
- Parameters
- test: Usually a boolean expression, but can be any value or variable.
- See here for true or false state of values.
- See here for boolean and logical operators
Tip: Do not confuse assignment '=' with equal '=='
- doWhenTrue: the expression to do when test evaluates to true.
- doWhenFalse: the expression to do when test evaluates to false
- test: Usually a boolean expression, but can be any value or variable.
Note: The true and false expressions may not define variables using assignment, '='. A syntax error will be emitted.
- Examples
a=1; b=2; c= a==b ? 4 : 5 ; // returns the number '5' a=1; b=2; c= a==b ? "a==b" : "a!=b" ; // returns the string "a!=b" a=5; test = a==1; // save boolean result echo( test ? true: false ); // false L = 75; R = 2; test = (L/R)>25; TrueVector = [test,L,R,L/R,cos(30)]; // define the true vector FalseVector = [test,L,R,sin(15)]; // define the false vector a1 = test ? TrueVector: FalseVector; // [true, 75, 2, 37.5, 0.866025]
Recursive function calls
The Conditional "?:" operator is of particular use in terminating a recursion.
Note: There is a limit for recursion to prevent an application crash. When a function or module calls itself enough times the function returns undef
.
Some forms of tail-recursion elimination are supported.
- Example
A function to sum the values in a vector from the Start index to the End index. When the 's' is not given it will default to zero, the first element of the vector, and the 'e' argument must be given by name. When the end index, 'e', is not given the let sets the local index, 'i', to the last index of the vector.
v = [10,20,30,40];
function sumv(v, s=0, e=undef) =
let( i = is_undef( e ) ? len(v)-1 : e )
i == s ?
v[i]
: v[i] + sumv(v, s, i-1 )
;
echo( sumv( v, 0, len(v)-1) ); // 100
echo( sumv( v ) ); // 100
echo( sumv( v, 1, 2 ) ); // 50
Formatting complex usage
Multiple nested conditionals can become difficult to understand. Formatting them like multi-line indented "if/else" statements is clearer.
// find the maximum value in a vector function maxv(v, m=-999999999999, i=0) = (i == len(v) ) ? m : (m > v[i]) ? maxv(v, m, i+1) : maxv(v, v[i], i+1); v=[7,3,9,3,5,6]; echo("max",maxv(v)); // ECHO: "max", 9
Assign Statement
[Deprecated: assign() will be removed in a future release. Use Let() instead]
Set variables to a new value for a sub-tree.
- Parameters
- The variables that should be (re-)assigned
- example:
for (i = [10:50])
{
assign (angle = i*360/20, distance = i*10, r = i*2)
{
rotate(angle, [1, 0, 0])
translate([0, distance, 0])
sphere(r = r);
}
}
for (i = [10:50])
{
angle = i*360/20;
distance = i*10;
r = i*2;
rotate(angle, [1, 0, 0])
translate([0, distance, 0])
sphere(r = r);
}
Let Statement
[Note: Requires version 2019.05]
Set variables to a new value for a sub-tree. The parameters are evaluated sequentially and may depend on each other (as opposed to the deprecated assign() statement).
- Parameters
- The variables that should be set
- example:
for (i = [10:50])
{
let (angle = i*360/20, r= i*2, distance = r*5)
{
rotate(angle, [1, 0, 0])
translate([0, distance, 0])
sphere(r = r);
}
}