N NezamDocumentation

Expressions#

The top-level expression grammar is singleExpression. Operators are parsed by precedence, from low-precedence pipelines down to primary expressions.

Operator precedence#

From lower to higher precedence:

AreaSyntax
Pipelinevalue |> next
Raise expressionraise expr
Assignment=, *=, +=, -=, /=, %=
Business operationscopy to, copy from, duplicate, transform, where, select, groupby, sort_by, take, skip, flat_map, find, fold, reduce, any, all, each
Conditionalcondition ? yes : no
Castvalue as Type
Null coalescinga ?? b
Logicaland, or, &&, ||
Equality==, equal, equals, !=
Null checksis null, is not null, is null or empty
Relational<, <=, >, >=, in, not in, contains, matches
Rangea..b, a...b
Arithmetic+, -, *, /, %, **
Prefix/postfixnot x, !x, await x, ++x, x++

Primary expressions#

Primary expressions include owner references, identifiers, literals, parenthesized expression sequences, object and array forms, lambdas, switch/when expressions, validation calls, HTTP requests, navigation calls, and query expressions.

bl
this
state
(amount, currency)

Object, array, and construction forms#

bl
let vendor = new Vendor(vendor_id_param);
let draft = new Vendor { name: "Acme" };
let values = [1, 2, ...more_values];
let names = [item.name for item in items where item.active];
let payload = {
  name: vendor.name,
  ["external-id"]: vendor.external_id,
  ...extra_payload
};

Object literal properties can use qualified names, string literals, numeric literals, computed literal or identifier keys in [] or (), and ...identifier spreads. Typed object literals support qualified property names, [expression] computed keys, and ...expression spreads. Array comprehensions use [expr for name in source] with an optional where filter.

Member access and calls#

bl
customer.name
customer?.address
items[0]
service.call(arg)
object.method<Customer>(value)

Call arguments can be positional, labeled, spread with ...expr, or *.

Lambdas#

bl
(x, y) -> x + y
x => x.total
function (x: integer) {
  return x;
}

Lambda bodies can be expressions or block statements.

Switch and when expressions#

bl
let label = switch (status) {
  case "open" -> "Open",
  case "closed" -> "Closed",
  default -> "Unknown"
};

let review = switch (status) {
  case "held" when amount > 1000 -> "review",
  default -> "normal"
};

let size = when {
  amount > 1000 -> "large",
  else -> "normal",
};

Query expressions#

Business Language also supports LINQ-style query expressions:

bl
let open_invoice_ids =
  from invoice in invoices
  where invoice.open_amount > 0
  orderby invoice.due_date ascending
  select invoice.invoice_id;

Joins are supported:

bl
let invoice_vendor_rows =
  from invoice in invoices
  join vendor in vendors on invoice.vendor_id == vendor.vendor_id
  select new { invoice: invoice.invoice_id, vendor: vendor.vendor_name };

Query expressions can use where, orderby, groupby, and join clauses. Query bodies can be combined with union, intersect, or except, each optionally followed by all. Parenthesized query subqueries may start with select or with.

bl
let invoice_ids =
  from invoice in open_invoices select invoice.invoice_id
  union all
  from invoice in held_invoices select invoice.invoice_id;

Validation and HTTP expressions#

bl
validate PostingPolicy(invoice)

get IntegrationClient "/vendors" {
  company: company_code_param
}

post "/vendors" payload

HTTP expression methods are get, post, put, delete, patch, head, and options. The target service is optional when the path expression is provided directly.

bl
navigate VendorForm(vendor_id_param)

Use navigation expressions for UI-driven transitions rather than encoding route strings in business logic.

Source: packages/business/language/expressions.md