Variables in Rules – Creating and Assigning

In the following article, we will explain how to use variables in rules. The article here explains how variables are created and assigned inside sequences. You’ll find a brief overview over the main syntax in our Cheat Sheet.

Creating variables and direct assignment of values

In rules you can define and assign variables either on the Left-Hand Side (LHS) or on the Right-Hand Side (RHS). Assigning variables on the RHS has to happen in an evaluation statement (eval{statement}). Assigning variables on the LHS is not needed often. It is more common to look for a pattern on the LHS and then do another if/else if check on the RHS. However, if you require variables on the LHS you can declare them and either directly assign a value or you yield an assign statement. Yielding (yield{statement}) enables to evaluate statements on the LHS, which is not typically supported.

rule myRule{
   // LHS
   def var strLHS:string = "hello"; //direct variable assignment
   yield {yield strLHS = "hello world";} //yield assignment
   def ref strArrLHS:array = array["hello", "world"]; //direct reference assignment
   yield {yield strarrLHS = array["hello", "beautiful", "world"];}
   yield {emit("strLHS: " + strLHS + " strArrLHS: " + strArrLHS + "\n");} //yield is also needed to emit from rules
   // RHS
   modify{
      def var strRHSo:string = "good"; //direct variable assignment
      eval{
         def var strRHS:string; //direct assignment as shown in LHS also possible;
         strRHS = "hello"; //no yield is required
         yield strRHSo = "good mood";
         emit("strRHS: " + strRHS + " strRHSo: " + strRHSo + " but you can also access values from the LHS, strLHS: " +strLHS + "\n"); //no yield required
      }
   }
}

}

The given examples cover strings, but the process is the same for other primitive types, element types (such as node or edge classes) or container types (such as arrays, sets, maps or deques).

NOTE: When creating container type variables you should always declare them as empty. Containers contain NULL by default which can cause errors when trying to operate with them. A container defined as empty will not cause such errors.

  1. In the modify part, the value of a variable can be directly assigned but not changed afterwards.
  2. You cannot yield from the RHS to variables defined on the LHS. However, you can access the values of variables defined on the LHS.
  3. Variables created inside eval can be manipulated without yield.

Assigning return values to primitive type variables

You can also assign return values of functions and procedures to primitive type variables created in rules:

rule myRule {
   def var FunctionValue:int = myFunction();
   modify{
      eval{
         def var MyFunctionValue:int = myFunction();
         (def var ProcedureValue:int) = myProcedure();
      }
   }
}

function myFunction:int{
   def var returnValue:int = 42;
   return(returnValue);
}

procedure myProcedure():(int){
   def var returnValue:int = 42;
   return(returnValue);
}

As you can see from above examples, you have to pay close attention to the parenthesis.

For functions: To call a function in a rule it needs a definition of a variable. Functions can only have one return value. Thus, assigning the return value to a variable can be done without further parenthesis. Functions can be called from LHS and RHS (modify and eval environment).

For procedures: To call a procedure in a sequence it needs the same structure as for functions. Procedures can have multiple return values. Thus, assigning the return value(s) to one or more variables requires the variable(s) to be enclosed in parenthesis within the curly brackets.
If the procedure returns more than one value, list the variable separated with commas  ( variable1, variable2, … ) = someProcedure . Order the variables according to the definition in your procedure.
Procedures can only be called inside the eval block.

Was this article helpful?

Related Articles