Functions

Assign

OpenSCAD's assign() statement will change the value of a variable for a sub-tree.
a = 5;
assign (a=20) {
    echo(a);
}; 

echo(a);
for (i = [10:2:50]){
    assign (angle = i*360/20, distance = i*10, r = i*2){
        rotate(angle, [1, 0, 0])
        translate([0, distance, 0])
        sphere(r = r);
        echo (angle);
    }
}
echo (angle);




Functions

OpenSCAD also supports user-defined functions for code readability and for re-use. You can define a function that will return a value based on the parameters you specify.

Syntax:
// Declaration of a function
 function name_of_my_func(param1,param2,...,paramn) =exp in function of myparameters;
Example:
my_d=20;
//Declaration of  function r_from_dia
function r_from_dia(my_d) = my_d / 2;

echo("Diameter ", my_d, " is radius ", r_from_dia(my_d));

//Declaration of  function f
function f(x)=3*x;
 
cube([f(2),f(2),f(2)],center=true);

Here is another example of user-defined functions:
//Code derived from clothbot

sphere_radius=10;
pts_on_sphere=4;


mySphere();

module mySphere(){
    color(.1,.1,0.1)
    sphere(r=sphere_radius);
    map2PointsOnSphere(radius=sphere_radius,N=pts_on_sphere)sphere(.5,$fn=64);
}

function pi()=3.14159265358979323846;

module map2PointsOnSphere(radius=1.0, N=3)assign(inc=pi()*(3-sqrt(5)),offset=2/N){
    for(k=[0:N-1]){
        assign(y=k*offset-1+(offset/2),r=sqrt(1-(k*offset-1+(offset/2))*(k*offset-1+(offset/2))),phi=k*inc){
            translate([radius*cos(360*phi/(2*pi()))*r,radius*y,radius*sin(360*phi/(2*pi()))*r])
            child(0);
         }
    }
}


Add a render() statement in the mySphere() module and then you can quickly render multiple spheres:
//Code derived from clothbot 

sphere_radius=10;
pts_on_sphere=4;

for(i=[0:10]){
translate([i*20,0,0]) mySphere();
}
mySphere();
module mySphere(){
    render(){
    color(.1,.1,0.1)
    sphere(r=sphere_radius);
    map2PointsOnSphere(radius=sphere_radius,N=pts_on_sphere)sphere(.5,$fn=64);
    }
}

function pi()=3.14159265358979323846;

module map2PointsOnSphere(radius=1.0, N=3)assign(inc=pi()*(3-sqrt(5)),offset=2/N){
    for(k=[0:N-1]){
        assign(y=k*offset-1+(offset/2),r=sqrt(1-(k*offset-1+(offset/2))*(k*offset-1+(offset/2))),phi=k*inc){
            translate([radius*cos(360*phi/(2*pi()))*r,radius*y,radius*sin(360*phi/(2*pi()))*r])
            child(0);
        }
    }
}


Here is another example:

//Code derived from  William A Adam's OpenSCAD Revolids version 0.5 
//=======================================
//                Constants
//=======================================
// The golden mean 
Cphi = 1.61803399;




torus(innerRadius = 15, size=[10,6]);


module PlaceQuad(quad) {
     PlaceTriangle([quad[0], quad[1], quad[2]]);
     PlaceTriangle([quad[0], quad[2], quad[3]]);
}

module PlaceTriangle(verts, reverse = 0) {
     if (reverse == true){
         polyhedron(points=[verts[0], verts[1],verts[2]], 
         triangles=[[0,1,2]]);
     } else {
         polyhedron(points=[verts[0], verts[1],verts[2]], 
         triangles=[[2,1,0]]);
     }
}






module torus(innerRadius=1, size=[1,1]){
    rotate([0, -90,0])
    surface_rotation_torus(offset=[0,innerRadius], 
        size = size, 
        anglesteps = 40, 
        sweepsteps = 40);
}



//===================================================
//             Parametric Surface Functions
//===================================================


// Point on the surface of a torus
function param_torus(offset, size, theta, phi) = 
    [offset[0]+size[0]*cos(theta), 
    (offset[1]+size[1]*sin(theta))*cos(phi), 
    (offset[1]+size[1]*sin(theta))*sin(phi)];

//        x=(c+a*cos(v))*cos(u)    
    
//        y=(c+a*cos(v))*sin(u)    

//        z=a*sin(v)    

//===================================================
//                Torus
//===================================================
//Theta is  used to represent an unknown angle. Theta represents an angle in degrees, but not in radians. 


module surface_rotation_torus(offset=[0,1], size=[0.5,0.5], anglesteps = 12, sweepsteps = 12){
    sstepangle = 360 / sweepsteps;    // phi
    astepangle = 360/ anglesteps;    // theta

    // Angle 0 <= phi <= 2pi
    for (sstep = [0:sweepsteps-1]){
        // Angle 0 <= theta <= 2pi
        for(astep = [0:anglesteps-1]){
            assign(p0 = param_torus(offset=offset, size = size, theta = astep*astepangle, phi = sstep*sstepangle))
            assign(p1 = param_torus(offset=offset, size=size, theta = (astep+1)*astepangle, phi = sstep*sstepangle))

            assign(p2 = param_torus(offset=offset,  size=size, theta = astep*astepangle, phi = (sstep+1)*sstepangle))
            assign(p3 = param_torus(offset=offset,  size=size, theta = (astep+1)*astepangle, phi = (sstep+1)*sstepangle))
            {
                //DisplayQuadFrame([p0, p1, p3, p2]);
                PlaceQuad([p0, p1, p3, p2]);
            }
        }
    }
}