This article contains several tips using the conditional ?| operator to simplify Lasso code for better speed and readability.
In Lasso there is often more than one way of accomplishing the same task. Choosing the best code for each job can be difficult, but making the right choice can make your code easier to read, maintain, and in some cases faster. This week's tip contains a number of code simplifying tips using the conditional ?| operator.
The conditional ? operator which was introduced in Lasso 8 can be used to streamline simple conditional operations. A common conditional statement like this:
If: !(Var_Defined: 'myVar');
Var: 'myVar' = 'A quick brown fox.';
/If;
...can be streamlined as follows using the ? operator rather than the [If] ... [/If] tags.
!(Var_Defined: 'myVar') ? Var: 'myVar' = 'A quick brown fox.';
When we look at several variable definitions in a row you can see how the ? operator can enhance readability. The following code defines three variables with default values if they are not already defined.
If: !(Var_Defined: 'myVar1');
Var: 'myVar1' = 'Alpha';
/If;
If: !(Var_Defined: 'myVar2');
Var: 'myVar2' = 'Beta';
/If;
If: !(Var_Defined: 'myVar3');
Var: 'myVar3' = 'Gamma';
/If;
The symmetry in the three statements is much more apparent in the code below. It is easier to see what the default values for the three variables is and it is easier to copy and paste one of the statements to create a fourth variable.
!(Var_Defined: 'myVar1') ? Var: 'myVar1' = 'Alpha';
!(Var_Defined: 'myVar2') ? Var: 'myVar2' = 'Beta';
!(Var_Defined: 'myVar3') ? Var: 'myVar3' = 'Gamma';
This construction can be used whenever a conditional is used simply to decide whether to run a single statement or not. If the conditional contains more than one statement then it is usually better to use a standard [If] ... [/If] statement.
One common use of the ternary ? | version of the conditional operator is to define the initial value of a variable based on a conditional. Rather than performing a conditional like this...
If: $age < 18;
Var: 'status' = 'minor';
Else;
Var: 'status' = 'adult';
/If;
... we can use an inline conditional as follows:
Var: 'status' = ($age < 18 ? 'minor' | 'adult');
In this simpler statement the variable name is not duplicated. Placing the conditional within the statement makes it clear that the conditional is selecting the value for the variable.
Variables are often used to hold values for only a very short period of time. The variable is defined, passed as a value to a tag or used as an operand in an expression, and then never referenced again. The penalty in speed and memory required by these variables is minimal. However, it can sometimes be beneficial to replace them with inline expressions.
For example, the $status variable above might be generated and passed into an inline to store the status of a person in a database record. That code is shown below.
Var: 'status' = ($age < 18 ? 'minor' | 'adult');
Inline: -Update,
-Database='People',
-Table='Person',
-Keyfield='ID',
-Keyvalue=$id,
'status' = $status,
-MaxRecords=0;
/Inline;
If the $status variable is used elsewhere on the page then this code works well. However, if the $status is never referenced again then the code can be simplified and sped up a little by embedding the $status expression directly in the inline as follows.
Inline: -Update,
-Database='People',
-Table='Person',
-Keyfield='ID',
-Keyvalue=$id,
'status' = ($age < 18 ? 'minor' | 'adult'),
-MaxRecords=0;
/Inline;
This code clarifies that the status is only going to be used to update a database record and is not required to be a variable. Since the $status variable is never created, Lasso does not have to allocate storage space to it or keep track of it until the end of page execution.
A similar technique can be used to generate dynamic inlines without the use of an array variable. The following code uses an array named $myInline to temporarily hold parameters which are fed into a dynamic -Update action.
Var: 'myInline' = Array;
If: (Action_Param: 'first') != '';
$myInline->(Insert: 'First_Name' = (Action_Param: 'first'));
/If;
If: (Action_Param: 'last') != '';
$myInline->(Insert: 'Last_Name' = (Action_Param: 'last'));
/If;
Inline: -Update,
-Database='People',
-Table='Person',
-Keyfield='ID',
-Keyvalue=$id,
$myInline,
-MaxRecords=0;
/Inline;
The same code can be written using inline conditionals as follows. Each conditional evaluates to an array of parameters which are passed into the inline or to Null which is ignored.
Inline: -Update,
-Database='People',
-Table='Person',
-Keyfield='ID',
-Keyvalue=$id,
(Action_Param: 'first') != '' ?
(Array: 'First_Name' = (Action_Param: 'first')),
(Action_Param: 'last') != '' ?
(Array: 'Last_Name' = (Action_Param: 'last')),
-MaxRecords=0;
/Inline;
If the inline has many optional parameters then it is often easier to use the array method. However, if only one or two parameters are optional in a complex inline then it is easier to insert a conditional directly into the inline rather than switching the methodology over to use an array.
Lasso tags are often written to accept different types of input and to do the right thing with it. For example, the [Auth_User] tag can be written as:
[Auth_User: 'ratchet']
... to authenticate a single user or as:
[Auth_User: -User=(Array: 'ratchet', 'bumblebee', 'jazz', 'ironhide', 'optimus prime')]
... to authenticate any of a collection of different users.
Within the definition of the tag it is necessary to process the -User parameter differently depending on whether a single username or an array of usernames has been passed. A portion of the code for this tag might look like this:
Define_Tag: 'Auth_User', -Required='User';
If: #user->IsA('array');
Iterate: #User, (Local: 'temp');
... check each username ...
/Iterate;
Else;
... check username ...
/If;
...
/Define_Tag;
There is duplication of the password checking code between the contents of the [Iterate] ... [/Iterate] tags and the single username case. However, if we use an inline conditional with the opening [Iterate] tag then we can use the same checking code for both cases. If the #user parameter is already an array then we pass it on, otherwise we create a single element array with the #user parameter.
Define_Tag: 'Auth_User', -Required='User';
Iterate: (#user->IsA('array') ? #User | (Array: #user)), (Local: 'temp');
... check each username ...
/Iterate;
...
/Define_Tag;
At the expense of a more complex opening [Iterate] tag we save a lot of duplication of effort within the tag. Since the code is no longer duplicated we eliminate the possibility that a change applied to one part of the code will not be applied to the other part as well.
Author: Fletcher Sandbeck
Created: 19 Oct 2007
Last Modified: 1 Mar 2011
Please note that periodically LassoSoft will go through the notes and may incorporate information from them into the documentation. Any submission here gives LassoSoft a non-exclusive license and will be made available in various formats to the Lasso community.
©LassoSoft Inc 2015 | Web Development by Treefrog Inc | Privacy | Legal terms and Shipping | Contact LassoSoft