vector

vector, keyword

The vector keyword declares a user-defined vector function when it appears after def.

‘def vector name«tables»(args) with’, vector function definition

A vector function binds table parameters between << and >>. Inside the function body, expect table declares the tables and dimensions required by the function. This declaration is optional for a table parameter with no dimension requirements.

Unlike pure and process functions, a vector function body may use table-prefixed vectors and may aggregate from one declared table into another.

The result can be a scalar, a vector on a table parameter, or a tuple. Returning a scalar does not require scalar-only inputs. Tuple components are broadcast to a common table; for example, returning a scalar alongside T.Value broadcasts the scalar to T.

To return a newly constructed table rather than values on existing tables, use def table.

Examples

def vector daysAfterFirstSale<<Products, Sales>>(
  Sales.Date : date) with
  expect table Products[sku]
  expect table Sales expect [sku]
  Products.FirstSale = first(Sales.Date) sort Sales.Date
  Sales.Age = Sales.Date - Products.FirstSale
  return Sales.Age

table Products[sku] = with
  [| as sku, as Label |]
  [| "shirt", "Shirt" |]
  [| "hat", "Hat" |]

table Sales = with
  [| as ProductSku, as Date, as Qty |]
  [| "shirt", date(2024, 1, 3), 2 |]
  [| "shirt", date(2024, 1, 8), 1 |]
  [| "hat", date(2024, 1, 5), 3 |]

keep where Sales.sku = Sales.ProductSku

Sales.DaysAfterFirst = daysAfterFirstSale<<Products, Sales>>(Sales.Date)

show table "Sales lines" with
  Sales.ProductSku
  Sales.Date
  Sales.Qty
  Sales.DaysAfterFirst

Scalar-only calls can use the vector-function pipeline and define local tables:

def vector innerSum(n : number) with
  table Inner = extend.range(n)
  return sum(Inner.N) when (Inner.N mod 2 == 0)

result = innerSum(6)

Table parameters can expose their primary dimension inside the vector function:

def vector shippedBefore<<Items, Orders>>(Orders.Qty : number) with
  expect table Items[id]
  expect table Orders expect [id]
  Items.Total = sum(Orders.Qty)
  return Items.Total

A scalar aggregation can be returned on its own or alongside a vector:

def vector totalQty<<T>>(T.Qty : number) with
  return sum(T.Qty) into Scalar

def vector shares<<T>>(T.Qty : number) with
  total = sum(T.Qty)
  return (total, T.Qty / total)

table Orders = with
  [| as Qty |]
  [| 10 |]
  [| 30 |]

total = totalQty<<Orders>>(Orders.Qty)
Orders.Total, Orders.Share = shares<<Orders>>(Orders.Qty)

show scalar "Total quantity" a1b1 with total
show table "Shares" a2d4 with
  Orders.Qty
  Orders.Total
  Orders.Share

The scalar total is 40. The table contains (10, 40, 0.25) and (30, 40, 0.75): the tuple’s scalar component is broadcast to each row.

Exporting a vector function

Vector functions can be exported from modules with export def vector. An importing script can call them through the module alias or import their name through a with block.

For example, the following module sums sales quantities per product:

// Module "/sample/sales-metrics"
export def vector totalQty<<Products, Sales>>(Sales.Qty : number) with
  expect table Products[sku]
  expect table Sales expect [sku]
  Products.Total = sum(Sales.Qty)
  return Products.Total

The importing script supplies its own tables and quantity vector:

import "/sample/sales-metrics" as Metrics

table Products[sku] = with
  [| as sku |]
  [| "shirt" |]
  [| "hat" |]

table Sales = with
  [| as Product, as Qty |]
  [| "shirt", 2 |]
  [| "shirt", 3 |]
  [| "hat", 4 |]

keep where Sales.sku = Sales.Product
Products.Total = Metrics.totalQty<<Products, Sales>>(Sales.Qty)

show table "Totals" a1d3 with
  sku
  Products.Total

The table shows a total of 5 for “shirt” and 4 for “hat”.

Remarks

Filters inside the function have the same scope as in the calling script. A vector initialized before a where block retains its initial values on rows excluded by that block. Returning it after the block returns the full vector, not just the selected rows. See the filtered calculation example.

Vector functions must be declared at the top level, not inside another block. A vector function name cannot have multiple overloads.

Vector functions cannot be called inside each, autodiff, or montecarlo blocks. This restriction concerns where the call appears, not which blocks can be used within the function body.

See also