Declarative Objectivity (DO) Language : Data Statements : LET Statement
LET Statement
A LET statement defines a global named value, or parameter, which can be used as an expression in other statements.
   
Syntax 
letStatement : letClause;
letClause : LET name '=' ( literal | structure | statement );
structure : collection | interval | object;
Quick Look 
Define a parameter and set it to a numeric value, and then use the parameter in another statement:
LET rf = 3.52;
UPDATE Location WHERE airportCode == 'SFO' SET rateFactor TO $rf;
Define a parameter and set it to a numeric value, then change the parameter to a string value:
LET zip = 95134;
LET zip = '95134';
Define a parameter that names an address value (a transient instance of the embeddable class Address):
LET addr = Address {city:'San Jose', state: 'CA'};
Define a parameter that names a list of date values:
LET myDays = LIST {2017/03/17, 2017/12/31, 2018/01/01};
Define a parameter that names the result of a statement (a list of projections containing the first and last names of all existing customers):
LET custs = FROM Customer RETURN firstName, lastName;
Set a parameter to a reference to a newly created customer, and use the parameter to create a new rental contract that references the customer:
LET newCust = CREATE Customer {firstName:'Mike', lastName: 'Suarez'};
CREATE RentalContract{customer: $newCust};
See also 
SHOW Statement  
SHOW PARAMETERS Statement   
Discussion 
A LET statement defines a parameter, which consists of a global name to which a value is assigned. You can use a parameter as an expression in subsequent DO statements by prefixing its name with the $ symbol. For example, the following statements define and then use the parameter ts to query for reservations with a particular timestamp:
LET ts = 2018/01/01 13:10:00;
FROM Reservations WHERE timestamp == $ts RETURN pickupLocation;
Parameters make statements easier to read. That is, you can simplify a statement by “factoring out” a lengthy or complex value expression, and assigning a short name to it. Furthermore, parameters make statements easier to reuse. That is, you can re-execute the same statement with a different value simply by executing another LET statement to change the value assigned to the parameter. For example:
// Change the parameter to another date-time value
LET ts = 2018/02/14 20:30:00;
FROM Reservations WHERE timestamp == $ts RETURN pickupLocation;
A parameter persists for the duration of the process in which it was defined. Its assigned value is retained unless a subsequent LET statement assigns a different value.
Use SHOW PARAMETERS to see the names and types of all currently defined parameters.
Use SHOW to see the current value of a parameter.
Parameter Names
A parameter name may be any well-formed identifier. As with DO language keywords, a given parameter name may be typed in any case. That is, the following statements define and then change the same parameter:
LET test = true;
LET TEST = false; 
You can verify this using a SHOW statement:
SHOW $test;
false
SHOW $TEST;
false
A parameter name is global in that is independent of any particular namespace or class. Consequently, it can be used freely in a statement, regardless of the class of the current context object.
Parameter Values
The value you assign to a parameter can be specified using a literal expression, a structure, or a statement, or some combination of these in an operator expression.
 
Use
To Specify This Type of Value
Examples
Boolean, Integer, Real, String, Character, Date, Time, DateTime, or Reference
// Integer values
LET x = 3;
LET y = ROUND(3.1415);
 
// Uppercased String value
LET nm = UPPER('Anderson');
 
// Reference value
LET oid = 3-3-4-121;
List, Set, or Map
// List of strings
LET srvrecs = LIST{'oil change', 'inspection'}
 
// Map of Customer objects
LET custs = MAP{'martin123':3-3-1-34, '009':3-3-1-5 }
Interval
// Interval value
LET numdays = INTERVAL{DAYS: 3}
Object (of an embeddable class)
// Transient Address Object
LET addr = Address {city:'San Jose', state: 'CA'};
Reference to a new object of a referenceable class 1
// Customer reference
LET newCust = CREATE Customer {lastName: 'Suarez'};
List of projections from deleted objects 2
// Customer reference
LET exCust = DELETE Customer WHERE userId == 'temp' RETURN *;
List of projections from returned objects 2
// List of Customer projections
LET custs = FROM Customer WHERE lastName == 'Suarez' RETURN firstName;
List of projections from updated objects 2
// List of Customer projections
LET chgd = UPDATE Customers WHERE userId == 'temp' SET pw TO userId;
Type Flexibility
You can assign a value of any type to a parameter. Assignment establishes the parameter’s current type. You can change the parameter’s type simply by assigning a value of a different type. For example, the following statements define and then change the same parameter, first to a numeric value and then to a string value.
LET zip = 95134;
LET zip = '95134';
This behavior makes a parameter significantly different from an attribute, which is a named value defined by a class. An attribute can only accept an assigned value of the type specified by its class.
Using Parameters as Expressions
You can use a parameter as an expression in another statement by prepending the $ symbol to the name you defined with LET. The parameter can then be used in any expression or clause, provided that the type of the parameter’s value is compatible with the context in which it is used.
For example, the following statements assign a DateTime value to a parameter called ts, and then use the expression $ts in both the WHERE and RETURN clauses:
LET ts = 2018/01/01 13:10:00;
FROM Reservations WHERE timestamp == $ts RETURN pickup - $ts;
In the WHERE clause, the parameter is compared for equality with the value of the DateTime attribute timestamp. In the RETURN clause, the parameter is subtracted from the value of the DateTime attribute pickup.
You can use a parameter in a statement that assigns a value to an attribute, provided the parameter and the attribute are of compatible types. For example, the following statements use $ts to initialize the timestamp attribute of a new Reservation object and to change the pickup attribute of an existing Reservation object:
LET ts = 2018/01/01 13:10:00;
CREATE Reservation{timestamp: $ts};
UPDATE Reservation WHERE timestamp == $ts SET pickup TO $ts;
You can use a parameter in an operator expression of any complexity. For example, the following statements assign a string value to a parameter, and then use the parameter to set the lastName and userId attributes. The userId attribute is set to 'ANDER456', which is the result of using several string operators to transform the parameter’s value:
LET nm == 'Anderson'
CREATE Customer{lastName: $nm, userId: SUBSTRING(UPPER($nm), 0,5)+'456'};
If the parameter is set to a value that has attributes or collection elements, you can use the parameter with selection operators. For example, the following LET statement defines a parameter addr whose value is a transient Address object in which several string attributes have been set. The parameter is then used to initialize the name and address attributes of a new Location object. Whereas the Location’s address attribute obtains all the Address object’s values, the name attribute is set by using the DOT operator to extract just the value of the Address object’s city attribute:
LET addr = Address{city: 'San Jose', state: 'CA'};
CREATE Location{name: $addr.city, address: $addr};
Using the Result of a CREATE Statement
As shown in the table above, you can define a parameter whose value is the result of a CREATE statement. In order to use such a parameter effectively, you need to understand some details about how the statement works and what it returns.
A CREATE statement:
Creates a new object.
Returns a reference to the newly created object.
Consequently, a parameter to which such a result is assigned can be used wherever a single reference value is accepted. For example, in the following statements, the value assigned to the parameter newCust is a reference that can then be assigned to the customer attribute of a particular RentalContract:
LET newCust = CREATE Customer {firstName:'Mike', lastName: 'Suarez'};
UPDATE RentalContract WHERE trackingNumber = 5 SET customer TO $newCust;
Using the Result of a RETURN, UPDATE, or DELETE Statement
As shown in the table above, you can define a parameter whose value is the result of a RETURN, UPDATE, or DELETE statement. In order to use such a parameter effectively, you need to understand some details about how the statement works and what it returns.
A RETURN, UPDATE, or DELETE statement:
Identifies a group of objects (the query source) that is optionally filtered by a WHERE clause.
Performs the requested action on each object of the filtered source.
Returns a projection corresponding to each processed object. A projection is a temporary object of an ad-hoc class that is similar to the source class, but includes just the attributes that were explicitly requested in the statement.
Consequently, when you assign the result of a RETURN, UPDATE, or DELETE statement to a parameter, the assigned value is a list of projections from which you can extract values using selection operators such as index subscripts and the DOT operator.
For example, in the following statement, the value assigned to the parameter freqCusts is a list of projections that each correspond to a Customer object with a qualifying number of reward points.
LET freqCusts = FROM Customer WHERE rewardPoints > 1200 RETURN firstName, lastName, rewardPoints;
Notice that each projection in the list contains the object identifier (OID) and the requested attribute values of a Customer object:
SHOW $freqCusts;
LIST
{
  Customer_Projection
  {
    __identifier__:3-3-1-5,
    firstName:'Jack',
    lastName:'Green',
    rewardPoints: 1350
  },
  Customer_Projection
  {
    __identifier__:3-3-1-67,
    firstName:'Fred',
    lastName:'Mertz',
    rewardPoints: 1500
  }
}
You can extract values from this list of projections just as you would any other list of objects. For example, the following statement includes expressions that use an index subscript to select the first projection in the list, and the DOT operator to extract the first and last names:
CREATE Customer{firstName: $freqCusts[0].firstName, lastName: $freqCusts[0].lastName + '_TEMP'}; 
Note:When you use index subscripts to select particular projections from a list of statement results, you should be aware that the element ordering within such a list may be different each time you execute the statement.
Obtaining a Reference to an Existing Object From a Parameter
A common task is to define a parameter from which you can extract a reference to an existing object. The extracted reference can then be used to form a relationship between the existing object and some other object.
For example, assume that the rental company is in the process of renting out a particular vehicle. To represent this, you want form a relationship between the object representing the vehicle, and the object representing the rental contract. Accordingly, the following statement queries for a Vehicle object with a particular license string, and assigns the result of the query to the parameter rented:
LET rented = FROM Vehicle WHERE license == '123ABC' RETURN license;
Because, by convention, license strings are unique in this data set, the query returns a list that contains a single projection, which corresponds to the Vehicle being rented:
SHOW $rented;
LIST
{
  Vehicle_Projection
  {
    __identifier__:3-3-4-205,
    license:'123ABC'
  }
}
You can use the rented parameter in an expression that extracts the Vehicle object’s reference. The following statement does so, and assigns the result of the expression to the vehicle attribute of the RentalContract of interest:
UPDATE RentalContract WHERE trackingNumber == 345 SET vehicle TO $rented[0].__identifier__ RETURN vehicle;
Notice that:
You must use an index subscript to select the returned projection, even if the list contains only a single projection.
You can use the DOT operator followed by the __identifier__ label to select the object identifier from a projection.