Waher.Script 2.15.0 language; the quickstart introduces expressions with their inputs and expected results.
Find the syntax you need
Values and names
Count and count can hold different values. Keep one spelling in your contract parameters, machine variables, and expressions. An unknown input is an error; define it before evaluation.
The language also supports complex numbers, big integers, rational numbers, physical quantities, and host-provided objects. Check the receiving parameter or XML value type before using them.
Assignment and comparison
5. := assigns; = compares. Use semicolons between statements. A newline is formatting, not a substitute for an unambiguous statement separator.
Operators
Multiplication binds more tightly than addition:
2+3*4 returns 14. Use parentheses for mixed expressions when they make the intended order clearer. XML attributes must escape < as < and & as &.
Conditions
"Complete". The condition chooses an expression result; it does not change the machine’s state by itself. State transitions are defined by the machine XML.
For a short expression, use condition ? valueIfTrue : valueIfFalse:
"Complete". With Count:=0, it returns "Waiting". Only the selected branch is evaluated. Prefer the longer if form when either branch needs a substantial calculation.
Null fallback
Use?? to provide a default when an optional input contains null:
"Untitled". A supplied 0 or false is retained: Value:=0; Value ?? 10 returns 0. Choose defaults that match your contract’s meaning; required values should be validated rather than silently replaced.
In this runtime, ?? also uses the fallback when evaluating its left side raises an error: Number("bad") ?? 10 returns 10. A missing variable can also trigger the fallback. Keep required-input validation explicit so a fallback does not conceal a misspelled name or invalid value.
Functions
81. Built-in functions and package extensions have their own signatures and context requirements. See functions and execution context.
Built-in function names are case-insensitive: abs(-3) and ABS(-3) each return 3. This differs from variable names. Use the documented function casing consistently.
Lambda expressions
A lambda defines a function with->. Put multiple arguments in parentheses:
36. Use a named function for a calculation you want readers to recognize; a lambda is useful when a function itself needs to be stored or passed as a value. See the original lambda reference for argument forms.
Variable scope in a function
A user-defined function evaluates with its own variable bindings. In the selected runtime, scalar assignments inside the function do not replace the caller’s bindings:5. The function’s argument and the assigned Count exist in the function call’s scope. A new variable created only inside that call is not available to the caller afterward.
Return a result and assign it in the caller when you want to update a value:
6. Function variable scope is separate from machine persistence. It is not a transaction rollback mechanism for mutable host objects or external actions. The supplied scope tests cover scalar bindings.
Loops
10. Keep work bounded when expressions execute as part of a contract or event. Language support for a loop does not guarantee a host permits every use of it.
Use foreach when you already have the values to process:
6. Use while when the condition determines how many iterations are needed:
3. Update the condition’s inputs so the loop can finish.
Collections
A vector groups ordered values. Indexes start at zero:20. Count(v) returns the number of entries; Sum(v) adds numeric entries.
Construct a matrix from row vectors. Matrix indexing uses column first, then row:
2, the second column of the first row. Both indexes start at zero.
An object groups named fields:
2. Operators can apply across collection elements: Sum([1,2,3]+10) returns 36. Confirm the returned shape when supplying a scalar contract parameter.
Ranges and comprehensions
A range supplies values to iterate over.1..4 includes 1, 2, 3, and 4. Add a step with |: 1..7|2 includes 1, 3, 5, and 7. For example, Sum(1..4) returns 10.
A comprehension creates a vector by evaluating an expression for each input:
[12,24,36]. Sum(Totals) returns 72. The expression before : produces each result; q in Quantities supplies its input.
To select existing values, put the source before : and the condition after it:
[2,3]. If no values match, the result is an empty vector. Filtering is useful for selecting values to process; it does not validate or reject the original input.
Use bounded inputs in contract expressions. See the original reference for comprehensions and element selection.
Unpack values
Assignment can match a vector pattern and bind its elements to names:36. The expected shape matters: assigning [3] to this two-element pattern fails. Check externally supplied data before unpacking it. See assignment pattern matching for more patterns.
Convert values explicitly
Number("12.5") returns numeric 12.5; String(12.5) returns the text "12.5". The aliases Num and Str are also tested in the selected core runtime. Number("not a number") raises an evaluation error.
Validate user input before conversion and avoid evaluating input as executable Script. See the tested function reference for precise examples and supported argument cases.
Errors
Handle invalid input before using it.2+ is a syntax error; UnknownInput+1 fails if the variable is absent. A false validation result is different from a failure to evaluate the expression.
The language supports try/catch/finally. For example:
0 in the selected core runtime. Only choose a fallback when it has the intended meaning; treating invalid payment input as zero can hide an error. A state machine also has XML-level failure controls. Verify the state reached after failure rather than suppressing an error that should reject an action.
Comments
Use// for a line comment and /* ... */ for a block comment. Explain why a rule exists rather than restating the expression. Comments are language text and must still be escaped if placed in an XML attribute.
Embed Script in XML
For a scriptable action attribute, wrap the calculated expression in braces, as invalue="{Count+1}". A literal such as content="Done" is not a script.
Calc and Script elements contain expression text directly. Use CDATA when it makes comparison operators easier to read:
PersistVariable action in a complete, validated machine.