2.2.2. The Read/Evaluate Cycle

When a DataHub script is run, the Gamma engine first parses the script, reading and evaluating each statement in turn. For functions or methods, first each argument gets evaluated, and then each statement gets evaluated. Variables get evaluated to their value. Literals like numbers, strings, arrays, and so on get evaluated to themselves. This read/evaluation cycle iterates through the progam on a recursive basis until the entire code gets read and evaluated. When the process is complete, the Gamma engine executes the code.

Preventing Evaluation

Sometimes you might not want the Gamma engine to evaluate a statement or variable when it parses the code. For example, when attaching an event handler to the .OnChange method, you don't want the code of the event handler to run until the event actually occurs. To prevent evaluation of a statement or variable, you can use the # character, a Gamma quote operator. Putting the # quote operator in front of any Gamma expression turns it into a literal, causing it to be evaluated to itself, as if it were a number or a string.

Procedure 2.1. Example 1

This example shows an interactive session with the Gamma engine in the Script Log. The --> symbols indicate where the user has input an expression, and the next line shows what the Gamma engine has returned as the result of evaluation.

  1. First we assign a value of 5 to the variable myvar:

    --> myvar = 5;
    5

    The Gamma engine returns the value of myvar, which is 5.

  2. Then we pass the variable myvar, to the Gamma engine:

    --> myvar;
    5

    The Gamma engine evaluates it and returns the value, 5.

  3. Now we pass the variable myvar, to the Gamma engine, this time quoted using the # symbol.

    --> #myvar;
    myvar

    And now the Gamma engine evaluates myvar as its literal name, myvar, The expression itself has passed through the evaluator intact, without being evaluated.

Partial Evaluation

In some circumstances you might need the Gamma engine to evaluate part of your statement, but not all of it. For this, there are two more quote operators. The ` quote operator indicates that this stament should not be evaluated, except for those places marked by the @ quote operator.

Procedure 2.2. Example 2

In this example, we use the the Gamma list function to illustrate how partial evaluation works. The list function creates a space-separated list out of its arguments

  1. First, let's define our variables and demonstrate the list function.

    --> myvar = 5;
    5
    --> yourvar = 9;
    9
    --> list(myvar, yourvar);
    (5 9)

    The Gamma engine first evaluates the arguments of the list function to 5 and 9, then applies the list function and puts them into a list: (5 9).

  2. Now let's use the # quote operator:

    --> list(#myvar, #yourvar);
    (myvar yourvar)
    --> #list(myvar, yourvar);
    (list myvar yourvar)

    First we quoted the individual arguments, then the entire expression. Do you see the difference in the result? The second return value, (list myvar yourvar) illustrates the internal syntax of the Gamma language, which is Lisp. Lisp functions are always of this syntax: (function_name arg1 arg2 ...).

  3. Now, suppose we want to partially evaluate the expression. First, let's use the ` quote operator alone:

    --> `list(myvar, yourvar);
    (list myvar yourvar)

    This gives the same result as the # operator, above. Now let's use the ` operator with the @ to allow partial evaluation, like this:

    --> `list(@myvar, @yourvar);
    (list 5 9)
    --> `list(myvar, @yourvar);
    (list myvar 9)

    In the first line, we prevented the evaluation of the list function itself, but allowed the Gamma engine to evaluate both of its arguments. In the second line, we allowed the evaluation of only one argument.

  4. Here are a few more examples, incorporating the Gamma string function, which turns an expression into a string:

    --> string(list(myvar, yourvar));
    "(5 9)"
    --> string(#list(myvar, yourvar));
    "(list myvar yourvar)"
    --> string(`list(@myvar, @yourvar));
    "(list 5 9)"
    --> `string(list(@myvar, @yourvar));
    (string (list 5 9))
    --> `string(@(list(myvar, yourvar)));
    (string (5 9))

    In each case, the ` quote operator prevents the evaluation of the overall expression, while the @ operator allows the evaluation of the sub-expression that immediately follows it.

  5. How does this apply to events in a typical DataHub script? Here is an example, using the .OnChange method in a class named Example with a method called MethodA:

    [Note]

    This the most important example, because this syntax is commonly used with the .OnChange method for handling events.

    class Example Application
    {
    ...
    }
    
    method Example.MethodA (x, y)
    {
    ...
    }
    
    method Example.constructor ()
    {
         .OnChange (#V1, `(@self).MethodA (#V1, #V2));
    }

    In this example, we want to apply MethodA of our Example class to the values of variable V1 and V2 at the exact moment when V1 changes its value. To do this we protect V1 and V2 from evaluation, using the # quote operator. We also do not want to evaluate the MethodA method, but we do have to evaluate the key variable indicating the class (self). So we use the ` operator to prevent the evaluation of the method, and the @ operator to allow the key variable self to be evaluated. This way the Gamma engine knows which class the .MethodA belongs to.

Forcing Evaluation

In some cases you might need to force the Gamma engine to evaluate an expression. For this, you can use the Gamma eval function. For example:

--> myvar = 5;
5
--> #myvar;
myvar
--> eval(#myvar);
5