def

The keyword def is used in Envision to introduce user-defined functions.

The function type can be pure, process, or vector.

‘def funtype funname (args) with’, function definition

User-defined functions can be introduced with def:

def pure helloWorld() with
  return "Hello World!"

def pure myMax(x : number, y : number) with
  if x > y
    return x
  else
    return x + y

def pure swap(a : text, b : text) with
  return (b, a) // wrapping '(..)' needed, indicates a tuple

show scalar "" with helloWorld() // Hello World!
show scalar "" with myMax(2, 17) // 17

a, b = swap("foo", "bar")
show summary "" with a /* bar */, b /* foo */

The return type is implicit, based on the returned values. Envision does not support expliciting the return type of user-defined function.

Functions must be declared before they are called. Recursion is not supported.

def pure factorial(a : number) with
  if a <= 1
    return 1
  return a * factorial(a - 1) // WRONG! recursive call not allowed

Overloading is allowed when argument types differ, but standard library names cannot be overloaded.

Function bodies are scalar: arguments and returns are table-free values, and table prefixes are not allowed inside the function body. Passing vectors to a function call triggers automatic vectorization by the runtime.

User-defined functions use positional arguments only; labeled arguments are reserved for selected built-in functions.

In pure and process functions, arguments and scalar parameters are read-only. Assigning to their names inside the function body is rejected.

Functions do not mutate their arguments or call options.

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

A vector function declares its table parameters between << and >>. Inside the body, expect table introduces those tables and the dimensions they require. Unlike pure and process, the body can use table-prefixed vectors and aggregate from one declared table into another.

def vector summarize<<P, S>>(S.Qty : number, S.Price : number) with
  expect table P[id]
  expect table S expect [id]
  P.TotalQty = sum(S.Qty)
  P.TotalAmount = sum(S.Qty * S.Price)
  return (P.TotalQty, P.TotalAmount)

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

table Sales = with
  [| as ProductId, as Qty, as Price |]
  [| "shirt", 2, 25 |]
  [| "shirt", 1, 25 |]
  [| "hat", 3, 10 |]

keep where Sales.id = Sales.ProductId

Products.TotalQty, Products.TotalAmount =
  summarize<<Products, Sales>>(Sales.Qty, Sales.Price)

show table "Products" with
  Products.Label
  Products.TotalQty
  Products.TotalAmount

The returned values must be vectors defined on one of the expected tables. Scalar parameters, if needed, are declared after ;, like in def process.

Context capture

Function bodies cannot access variables from the surrounding script, except for const values defined above the function.

const scale = 1.2

def pure applyScale(x : number) with
  return x * scale

show scalar "" with applyScale(10) // 12

Pure functions can only call other pure functions. Process functions can call both pure and process functions.

See also

User Contributed Notes
0 notes + add a note