Immutable Values with define and bind
Goal: name values without introducing mutation or moving pure logic into a handler.
Syntax
Module constant:
define Name as Type = literal
Local value inside a block:
bind name as Type = expression
define is visible in the module. bind is visible only in the flow where it is
declared.
Example
module examples.review_score
define ScoreLimit as Float = 0.75
define AcceptedLabel as Text = "accepted"
define ReviewLabel as Text = "review"
function ReviewScore
takes score as Float
takes bonus as Float
gives Text
do
bind adjusted as Float = (score + bonus) / 2.0
bind accepted as Boolean = adjusted >= ScoreLimit
if accepted
give AcceptedLabel
else
give ReviewLabel
Compile
touba compile review-score.tb --out review-score.air.json
The AIR contains:
- constants in
definitions.constants; - pure calculations in AIR expressions;
- local
bindvalues as graph nodes.
Run
touba run review-score.air.json --inputs-json '{"score":1.0,"bonus":0.8}' --output result
Expected output:
"accepted"
The output is a JSON string, including the quotation marks. Invalid, missing or extra entry fields are refused before execution. You can check the typed entry refusal without changing the program:
if touba run review-score.air.json --inputs-json '{"score":"invalid","bonus":0.8}' --output json; then
exit 1
else
test "$?" -eq 1
fi
Useful Errors
This constant is refused:
define BaseScore as Float = 0.5
define ScoreLimit as Float = BaseScore + 0.25
Reason: define accepts only literals. The calculation must live in a
function or in a local bind.
This local value is refused:
bind accepted as Boolean = title
Reason: the declared type is Boolean, while the expression produces Text.
Takeaway
Use define for non-sensitive thresholds or labels. Use bind to make a local
calculation readable and traceable.
Do not use define for an API key, token, environment variable, or value that
changes across execution environments.