Expressions
Expressions are the closest constructs PFA has to "code". They are evaluated in the context of predefined variables and most return a value.
There are four fundamental types of expressions:
- literal values (constants)
- symbol references (variables)
- special forms (language constructs like
if
andwhile
) - function calls (including operators like
+
and-
)
Every top-level field that can take a single expression can take a JSON array of expressions— the return value is the last expression in the array.
Example Expressions
All of the following expressions return the number 3.
1
3
1
{"+": [2, 1]}
1
{"+": [{"+": [1, 1]}, 1]}
1 2 3 4
[{"let": {"x": 0}}, {"set": {"x": {"+": ["x", 1]}}}, {"set": {"x": {"+": ["x", 1]}}}, {"x": {"+": ["x", 1]}}]
Literal values¶
The following are all possible forms of literal values:
JSON form | Examples | Description |
---|---|---|
null | null |
Only value of type “null”. |
boolean | true , false |
Only values of type “boolean”. |
integer | 3 , -3 |
Easy way to express integers. |
floating-point number | 3.0 , -3.14 , 1e8 |
Easy way to express double-precision numbers. |
bracketed string | ["hello"] |
Easy way to express a string, but it can only be used in contexts where a JSON array of expressions is illegal (otherwise, hello would be interpreted as a variable name in a single-expression array). |
singleton JSON object | {"int": 3} |
Explicit declaration of type. |
{"long": 3} |
||
{"float": 3} |
||
{"double": 3} |
||
{"string": "hello"} |
More explicit than ["hello"] and therefore less prone to error. | |
{"base64": "aGVsbG8="} |
Base-64 may be a more convenient way to express binary sequences. | |
type-value special form | {"type": "int", "value": 3} |
Any Avro type can be used in the "type" field; works for arrays, maps, records, unions, etc. |
The type-value special form may be used as an alternative to base-64 for binary sequences, since the JSON value of a bytes type is a raw string:
{"type": "bytes", "value": "hello"}
versus
{"base64": "aGVsbG8="}
Symbol references¶
A JSON string in a context where an expression is expected is always interpreted as a symbol reference.
Example¶
In the following, "input" is a variable and "hello" is a string.
{"s.concat": ["input", {"string": "hello"}]}
or
{"s.concat": ["input", ["hello"]]}
Special forms¶
Special forms are JSON objects with specified structure. Each special form is unique: see the special forms page for details.
Function calls¶
Function calls have the following forms for zero arguments, one argument, and more than one arguments.
{"function.name": []}
or
{"function.name": "argument"}
or
{"function.name": ["arg1", "arg2", "arg3"]}
Library functions are built into PFA and user-defined functions are declared in the fcns section of a PFA document. See the function library for a list of all predefined functions.
In the fcns section, user-defined functions must be declared with names that have no dots (.
), but when they are called, they are always prepended by u.
to avoid collisions with library functions.
Example¶
A function declared as
1 2 3 4 5 6 7 8 9 10 |
|
{"u.addone": ["oldarray", "newitem"]}
Source