Keywords · LET
LET
A LET binds a name to the result of a single expression — reactive in a body, a
constant at module or type level.
Format
The grammar of a single LET line:
LET ::= "LET" [ type ] identifier "=" ( expression | constantExpression )
type ::= name [ "(" type { " " type } ")" ]
expression ::= name { " " argument }
constantExpression ::= constant | name { " " constant }
argument ::= name | constant
constant ::= string | integer | number
name ::= identifier { "." identifier }
identifier ::= letter { letter | digit }
LET keyword is followed by an optional type, then a name, and after the =
either an expression — a function name applied to arguments — or a
constant expression — a constant, or a type constructor applied to constants. An
argument is itself a name or a constant, and a constant is a string, integer, or number.Usage
A LET keyword can live at the Root, or inside
FUNCTION,
REVERSE,
WITH,
MODULE, and
TYPE keywords.
At the Root
At the program's run root, a LET is a Root binding in the code that actually runs.
LET Maths.Real squared = Maths.Real.Multiply radius radius
LET Maths.Real area = Maths.Real.Multiply 3.14159 squared
The type comes first, then the name, then the expression. Change radius and both
bindings settle again, in order.
Inside a FUNCTION
A derived binding in the function body, recomputed reactively as its inputs change.
FUNCTION Maths.Real Area
INPUT Maths.Real radius
LET Maths.Real squared = Maths.Real.Multiply radius radius
LET Maths.Real area = Maths.Real.Multiply 3.14159 squared
Each LET names one step of the body, and the compiler recomputes a binding only when a
value it read has changed.
Inside a REVERSE
Part of a write-back body, preparing the value that the closing
SET pushes back.
REVERSE Ui.Form.Result submissionReverse
LET Ui.Form.Result result = Api.Client.ParseFormResult httpResponse
SET formDataState = result
LET parses the value the closing SET pushes into outer state.The LET bindings compute from the incoming value exactly as in a forward block,
preparing what the final SET writes back.
Inside a WITH
A binding in a WITH block, computed with the swapped module implementation in place.
WITH Logic = Ui.Logic
LET Ui.Element panel = Ui.Content.Panel content
Logic to Ui.Logic.The LET runs under the override, so every name it reaches for as Logic is
served by the replacement until the block ends.
Inside a MODULE
At module level a LET declares a named constant — a fixed value in the
module's namespace, not running code.
MODULE Palette
LET Colour.RGB Brand = Colour.RGB 0.1 0.4 0.9
The expression must be a constant — a literal, or a type constructor applied to literals
— so the value is fixed once, with no inputs or reactive dependencies. It is reached through the
module's name, as Palette.Brand.
Inside a TYPE
A type doubles as a namespace, so a LET inside it declares a constant reached through the
type's name.
TYPE Colour.RGB
FIELD Maths.Real red
FIELD Maths.Real green
FIELD Maths.Real blue
LET Colour.RGB Black = Colour.RGB 0.0 0.0 0.0
Colour.RGB.Black.The constant follows the type's FIELD lines
and is named through the type — here Colour.RGB.Black. As at module level, its value
must be a constant expression.
Can Contain
A LET is a leaf: it takes a type, a name, and a single expression on the
right of the =. In a body that is normally one call with plain-value arguments, recomputed
reactively; at MODULE or
TYPE level it must be a constant — a
literal or a type constructor applied to literals. Either way it opens no indented lines and contains no
further keywords.
Targets
The same example, rendered to each target.
JavaScript
var squared = Maths.Real.Multiply(radius, radius);
var area = Maths.Real.Multiply(3.14159, squared);
TypeScript
const squared = Maths.Real.Multiply(radius, radius);
const area = Maths.Real.Multiply(3.14159, squared);
Dart
final squared = Maths_Real.Multiply(radius, radius);
final area = Maths_Real.Multiply(3.14159, squared);
Swift
let squared = Maths.Real.Multiply(radius, radius)
let area = Maths.Real.Multiply(3.14159, squared)
Go
squared := Maths_Real.Multiply(radius, radius)
area := Maths_Real.Multiply(3.14159, squared)
Rust
let squared = cubelogix_runtime::real_multiply(radius, radius);
let area = cubelogix_runtime::real_multiply(3.14159, squared);
Zig
const squared = maths.real.multiply(radius, radius);
const area = maths.real.multiply(3.14159, squared);
JSON
["=", "squared", "Maths.Real", ["Maths.Real.Multiply", [], ["radius", "radius"]]],
["=", "area", "Maths.Real", ["Maths.Real.Multiply", [], [["#", "", "Maths.Real", "3.14159"], "squared"]]]
Related
A changeable cell is a STATE; a function returns its last
value with a trailing = (see FUNCTION), and
a REVERSE may use LET lines before it writes
back. The reactive model is covered in Reactive. Back to
the language.