Code Along

A code-along is a story about coding in which you are encouraged to “code up” all the examples gray kangarooin the story. In a code-along you should not cut-and-paste.

In this code along, we will explore wrapper functions, which are functions whose primary purpose are to call other functions. We use the term target function to denote the primary function called by a wrapper function.

A wrapper function provides an opportunity to intercept the arguments (i.e., actual parameters) being passed to its target function. A wrapper function can analyse, inspect, and/or record information about how its target function is being used. A wrapper function can also modify the arguments that are passed to its target function.

Code Along Example 1

The code below creates a simple “smiley face”, using a sequence of put2D function calls.

open Level_3;

fun smiley(x,z) = 
    (
wrapper_1
        put2D (11,8) YELLOW (x,z);    
                            
        put2D ( 5,1) BLACK  (x+3,z+2);
                            
        put2D ( 1,1) BLACK  (x+2,z+3);
        put2D ( 1,1) BLACK  (x+8,z+3);
                            
        put2D ( 1,1) BLUE   (x+4,z+4);
        put2D ( 1,1) BLUE   (x+6,z+4)
    );
    
build2D(32,32);

smiley(0,0);

show2D "smiley";

Code Along Example 2

In this example, we create a wrapper function, called myPut, whose target function is put2D. Note that in the body of the function smiley, all calls to the function put2D have been replaced by calls to the function myPut. Also note that, in this example, the function myPut takes the same arguments in the same order as its target function put2D. This makes the translation from put2D function calls to myPut function calls straightforward.

In this example, the purpose of the wrapper function is to stretch the artifact created by the smiley function. Choices for stretching are: (1) stretch only along the x-axis, (2) stretch only along the z-axis, (3) stretch by the same amount along the x-axis and z-axis, and (4) stretch by different amounts along the x-axis and z-axis.

The wrapper function in the code below stretches smiley along the z-axis by a factor of 2.

open Level_3;

fun myPut (xSize,zSize) brick (x,z) =
    put2D (xSize,2*zSize) brick (x,2*z);

fun smiley(x,z) = 
    (
wrapper_2
        myPut (11,8) YELLOW (x,z);    
                       
        myPut ( 5,1) BLACK  (x+3,z+2);
        
        myPut ( 1,1) BLACK  (x+2,z+3);
        myPut ( 1,1) BLACK  (x+8,z+3);
        
        myPut ( 1,1) BLUE   (x+4,z+4);
        myPut ( 1,1) BLUE   (x+6,z+4)
    );
    
build2D(32,32);

smiley(0,0);

show2D "smiley";

Code Along Example 3

In this example, the a wrapper function called myPut is created whose purpose is to print all the coordinates which are passed as arguments to the function put2D.

open Level_3;

fun myPut (xSize,zSize) brick (x,z) =
    (
        print ("\n(x,z) = (" 
               ^ Int.toString x 
               ^ "," ^ Int.toString z ^ ")");
        put2D (xSize,zSize) brick (x,z)
    );

fun smiley(x,z) = 
    (
        myPut (11,8) YELLOW (x,z);    
                       
        myPut ( 5,1) BLACK  (x+3,z+2);
        
        myPut ( 1,1) BLACK  (x+2,z+3);
        myPut ( 1,1) BLACK  (x+8,z+3);
        
        myPut ( 1,1) BLUE   (x+4,z+4);
        myPut ( 1,1) BLUE   (x+6,z+4)
    );
    
build2D(32,32);

smiley(0,0);

show2D "smiley";

Recall that the function print is an SML function which, when passed a string value as an argument, will display the string value to standard out. In Bricklayer, standard out is the command prompt window where feedback on Bricklayer programs (e.g., syntax errors) is displayed. The body of the function smiley contains six calls to the wrapper function myPut. The coordinate values for each of these calls is (0,0), (3,2), (2,3), (8,3), (4,4), and (6,4). These values are displayed in the command prompt window below.

wrapper_3