Function Statements
Function Statements
Function statements define reusable custom functions that can be called throughout your Trilogy scripts.
Syntax
function: "def" IDENTIFIER "(" function_binding_list ")" "->" expr
function_binding_item: IDENTIFIER function_binding_type? function_binding_default?
function_binding_type: ":" (data_type | validated_type)
function_binding_default: "=" expr
Basic Function
Define a simple function:
def double(x) -> x * 2;
With Type Hints
Specify parameter types:
def calculate_tax(amount: float, rate: float) -> amount * rate;
With Default Values
Provide default parameter values:
def apply_discount(price, discount = 0.1) -> price * (1 - discount);
Calling Functions
Use @ prefix to call custom functions:
def format_currency(amount) -> concat('$', cast(round(amount, 2) as string));
select
order.id,
@format_currency(order.total) -> formatted_total
;
Complex Functions
Functions can use expressions, including conditional logic:
def categorize_amount(amount) ->
case
when amount > 1000 then 'high'
when amount > 100 then 'medium'
else 'low'
end;
Constrained Parameters
Constrained parameter types reject out-of-domain literal arguments:
def discounted(price: float, rate: float[0..1] = 0.1) -> price * (1 - rate);
select @discounted(100.0, 0.2) as discounted_price;
Passing 2.0 as the rate is an authoring error. A concept argument is not scanned when a function is called; its data constraints belong on the concept declaration and are checked through datasource validation.
Reusable Assertions
Functions can return a boolean aggregate check for datasource assert clauses:
def retains_rows(row_id, fraction = 0.75) ->
count(row_id) >= fraction * prior(count(row_id));
key record_id int;
datasource records (record_id)
grain (record_id)
address records
assert @retains_rows(record_id)
;
prior(...) is only meaningful within a datasource assertion. Functions from an aliased module are called as @alias.function_name(...); see Functions & Imports.
Use Cases
- Reusable business logic
- Standardized calculations
- Code organization
- DRY principle
Example
# Define helper functions
def margin(revenue, cost) -> (revenue - cost) / revenue;
def growth_rate(current, previous) -> (current - previous) / previous * 100;
import order as order;
select
order.product_id,
sum(order.revenue) -> total_revenue,
sum(order.cost) -> total_cost,
@margin(total_revenue, total_cost) -> profit_margin
;