The code below shows four different ways of building a LEGO “thing”. The first thing is built (directly) through a sequence of “put2D” Bricklayer function calls. The second thing is built (indirectly) by calling a nullary function, named thing2, whose body consists of the exact same sequence of “put2D” Bricklayer function calls used to create the first thing. The third thing is built (indirectly) by calling a parameterized function, named thing3, whose body consists of a parameterized version of the sequence of “put2D” Bricklayer function calls used to create the first and second things. The fourth thing is built (indirectly) by calling a parameterized function, named thing4, whose body is mathematically equivalent to the body of the function thing3. The only difference between thing3 and thing4 is that in the body of thing4 mathematical axioms have been used to simplify expressions.

open Level_2; 

fun thing2 () =
    (concept-12-thing2        put2D_2x1_RED (0,0);
        put2D_2x1_RED (2,0);
        put2D_2x1_RED (1,1);
        put2D_2x1_RED (0,2);
        put2D_2x1_RED (2,2)
    );

fun thing3 (x,z) =
    (
        put2D_2x1_RED (x+0,z+0);
        put2D_2x1_RED (x+2,z+0);
        put2D_2x1_RED (x+1,z+1);
        put2D_2x1_RED (x+0,z+2);
        put2D_2x1_RED (x+2,z+2)
    );

fun thing4 (x,z) =
    (
        put2D_2x1_RED (x  ,z);
        put2D_2x1_RED (x+2,z);
        put2D_2x1_RED (x+1,z+1);
        put2D_2x1_RED (x  ,z+2);
        put2D_2x1_RED (x+2,z+2)
    );

(* ================================================ *)
build2D(32,32);

(* first thing - a sequence of "put2D" Bricklayer 
   function calls *)
put2D_2x1_RED (0,0);
put2D_2x1_RED (2,0);
put2D_2x1_RED (1,1);
put2D_2x1_RED (0,2);
put2D_2x1_RED (2,2);

setOffset2D(6,0);
(* second thing - a nullary function call *)
thing2();

setOffset2D(0,0); 
(* resetting the offset, since we will not need it *)

(* third thing - a parameterized function call *)
thing3(12,0);

(* fourth thing - a parameterized function call *)
thing4(18,0);

show2D "Things";

How It Works

The meaning of a function call can be understood in terms of a concept called unfolding. To unfold a function call, you replace the call to the function with the body of the function. For nullary functions, unfolding is very easy and can be accomplished using the copy-and-paste capabilities of a text editor. Unfolding a parameterized function call requires copy-and-paste and a substitution.

Function Call Code that gets executed
thing2 (); (
put2D_2x1_RED (0,0);
put2D_2x1_RED (2,0);
put2D_2x1_RED (1,1);
put2D_2x1_RED (0,2);
put2D_2x1_RED (2,2)
)
thing3 (0,1); (
put2D_2x1_RED (0+0,1+0);
put2D_2x1_RED (0+2,1+0);
put2D_2x1_RED (0+1,1+1);
put2D_2x1_RED (0+0,1+2);
put2D_2x1_RED (0+2,1+2)
);

Note that executing the function call “thing2 ()”  is the same as executing its body. Executing the function call “thing3 (0,0)” is the same as executing its body, provided the following substitutions are made. In the body of the function thing3, all occurrences of x should be replaced with 0, and all occurrences of z should be replaced by 1. This replacement is called a substitution. We will use the notation below to express this substitution.

[x → 0, z → 0]