# 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 and while)
• 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 "fcns": { "addone": { "params": [ {"old": {"type": "array", "items": "string"}}, {"newitem": "string"} ], "ret": {"type": "array", "items": "string"}, "do": {"a.append": ["old", "newitem"]} } } 
would be accessed as {"u.addone": ["oldarray", "newitem"]}