Expr Syntax Guide
This document provides a comprehensive guide to TVA expr syntax, covering function calls, pipelines, lambda expressions, and multi-expression evaluation.
Expression Elements
TVA expressions are composed of the following atomic elements:
| Element | Syntax | Description |
|---|---|---|
| Column Reference | @1, @col_name | Reference input data columns |
| Variable | @var_name | Variables bound via as |
| Literal | 42, "hello", true, null, [1, 2, 3] | Constant values |
| Function Call | func(args...) | Built-in functions |
| Lambda | x => x + 1 | Anonymous functions |
Evaluation Rules
- Expressions are evaluated left-to-right according to operator precedence
- The pipe operator
|has the lowest precedence, used to connect multiple processing steps - The last expression’s value is the result
Function Call Syntax
Prefix Call
func(arg1, arg2, ...) - Traditional function call syntax.
tva expr -E 'trim(" hello ")' # Returns: hello
tva expr -E 'substr("hello world", 0, 5)' # Returns: hello
tva expr -E 'max(1, 5, 3)' # Returns: 5
Method Call
Method call is syntactic sugar for function calls:
# Method call is equivalent to function call
@name.trim() # Equivalent to: trim(@name)
@price.round() # Equivalent to: round(@price)
# Method chaining
@name.trim().upper().substr(0, 5)
# Equivalent to: substr(upper(trim(@name)), 0, 5)
# Method call with arguments
@name.substr(0, 5) # Equivalent to: substr(@name, 0, 5)
@price.pow(2) # Equivalent to: pow(@price, 2)
Pipe Call (Single Argument)
arg | func() or arg | func(_) - Pipe left value to function. The _ placeholder can be omitted for single-argument functions.
tva expr -E '"hello" | upper()' # Returns: HELLO
tva expr -E '"hello" | upper(_)' # Returns: HELLO
tva expr -E '[1, 2, 3] | reverse()' # Returns: [3, 2, 1]
tva expr -E '" hello " | trim() | upper()' # Chain multiple pipes
Pipe Call (Multiple Arguments)
arg | func(_, arg2) - Use _ to represent the piped value.
tva expr -E '"hello world" | substr(_, 0, 5)' # Returns: hello
tva expr -E '"a,b,c" | split(_, ",")' # Returns: ["a", "b", "c"]
tva expr -E '"hello" | replace(_, "l", "x")' # Returns: "hexxo"
Expression Composition
Expressions can be combined in several ways:
- Operator Composition:
@a + @b,@x > 10 and @y < 20 - Pipe Composition:
@name | trim() | upper() - Variable Binding:
expr as @var; @var + 1 - Function Nesting:
if(@age > 18, "adult", "minor")
Lambda Expressions
Lambda expressions create anonymous functions, primarily used with higher-order functions like
map, filter, and reduce:
Syntax
| Form | Syntax | Example |
|---|---|---|
| Single parameter | param => expr | x => x + 1 |
| Multiple parameters | (p1, p2, ...) => expr | (x, y) => x + y |
Note: Lambda parameters are lexically scoped and do not use the @ prefix. This
distinguishes them from column references (@col) and variables (@var).
Examples
# Single-parameter lambda
tva expr -E 'map([1, 2, 3], x => x * 2)'
# Returns: [2, 4, 6]
# Multi-parameter lambda
tva expr -E 'reduce([1, 2, 3], 0, (acc, x) => acc + x)'
# Returns: 6
# Filter with lambda
tva expr -E 'filter([1, 2, 3, 4], x => x > 2)'
# Returns: [3, 4]
# Sort by computed key
tva expr -E 'sort_by(["cherry", "apple", "pear"], s => len(s))'
# Returns: ["pear", "apple", "cherry"]
Lambda bodies can reference columns (@col) and variables (@var) from the outer scope.
Complex Pipelines
The pipe operator | enables powerful function chaining:
# Chain single-argument functions
tva expr -n "name" -r " john doe " -E '@name | trim() | upper()'
# Returns: JOHN DOE
# Mix single and multi-argument functions
tva expr -n "desc" -r "hello world" -E '@desc | substr(_, 0, 5) | upper()'
# Returns: HELLO
# Complex validation pipeline
tva expr -n "email" -r " Test@Example.COM " -E '@email | trim() | lower() | regex_match(_, ".*@.*\\.com")'
# Returns: true
# Data transformation pipeline
tva expr -n "data" -r "1|2|3|4|5" -E '@data | split(_, "|") | map(_, x => int(x) * 2) | join(_, "-")'
# Returns: "2-4-6-8-10"
Multiple Expressions
Use ; to separate multiple expressions, evaluated sequentially:
# Multiple expressions with variable binding
tva expr -n "price,qty" -r "10,5" -E '@price as @p; @qty as @q; @p * @q'
# Returns: 50
# Pipeline and semicolons
tva expr -n "price,qty" -r "10,5" -E '
@price | int() as @p;
@p * 2 as @p;
@qty | int() as @q;
@q * 3 as @q;
@p + @q
'
# Returns: 35
Rules:
- Each expression can have side effects (like variable binding)
- Only the last expression’s value is returned
- Variables are scoped to the current expression evaluation
Comments
TVA supports line comments starting with //. Comments are only valid inside expressions; comments
in command line are handled by the Shell.
# With comments explaining the logic
tva expr -n "total,tax" -r "100,0.1" -E '
@total | int() as @t; // Convert to integer
@tax | float() as @r; // Convert tax rate to float
@t * (1 + @r) // Calculate total with tax
'
# Returns: 110
tva expr -n "price,qty,tax_rate" -r "10,5,0.1" -E '
// Calculate total price
@price * @qty as @total;
@total * (1 + @tax_rate) // With tax
'
# Returns: 55
Output Behavior
In tva expr, the last expression’s value is printed to stdout:
# Simple expression output
tva expr -E '42 + 3.14' # Prints: 45.14
# Column reference output
tva expr -n "name" -r "John" -E '@name' # Prints: John
# List output
tva expr -E '[1, 2, 3]' # Prints: [1, 2, 3]
The print(val, ...) function outputs multiple arguments sequentially and returns the last
argument’s value. If print() is the last expression, the value won’t be printed twice:
# Print intermediate values
tva expr -n "price,qty" -r "10,5" -E '
@price | print("price:", _);
print("qty:", @qty);
@price * @qty
'
# 10 price:
# qty: 5
# 50
Error Handling
Expression evaluation can produce several types of errors:
| Error | Example | Description |
|---|---|---|
| Column not found | @nonexistent | Column name doesn’t exist in headers |
| Column index out of bounds | @100 | Index exceeds number of columns |
| Type error | "hello" + 5 | Invalid operation for type |
| Division by zero | 10 / 0 | Cannot divide by zero |
| Unknown function | unknown() | Function not defined |
| Wrong arity | substr("a") | Wrong number of arguments |
Best Practices
- Use parentheses for clarity:
(a + b) * cvsa + b * c - Chain with pipes for readability:
@data | trim() | upper()instead ofupper(trim(@data)) - Bind intermediate results: Complex expressions benefit from variable binding
- Use comments: Explain non-obvious logic with
//comments - Handle nulls explicitly: Use
default()orif()for null handling