Veila

Functions

Declaring functions

In Veila, functions begin with a #, followed by a parenthesized list of parameters:

# (a, b) a + b + 3

This is an anonymous function that returns the sum of a, b, and 3.

The function body can be written on multiple indented lines. The last expression is the return value.

# (a, b)
   c ← a + b
   c + 2

The parameter and return types can be specified:

# (a: integer, b: integer): integer
   a + b + 3

Functions are given names the same way other values are:

plus-two ← # (a, b)
   c ← a + b
   c + 2

Aliases

To help with typing, functions whose names contain Unicode characters may also have an alias, which follows the standard name in parentheses. For example, multiplication is defined as:

× (*) ← #([n: numerical], [n] → [n]) #external

The formatter will replace occurrences of * with × where applicable. Note: It’s possible for multiple functions to share the same alias, as long as the function type makes it unambiguous.

Calling functions

To call a function, place the arguments after the function name. When a function accepts only one parameter, the parenthesis can be omitted:

f 2
g(1, 2)

Binary functions can be infixed; in fact, the mathematical operators are just regular functions:

1 + 2 – Equivalent to +(1, 2)

As a result, an expression with multiple elements will evaluate from left to right:

1 + 2 * 3 / 4 – Equivalent to (((1 + 2) * 3) / 4)

As demonstrated above, terms are left-associative, and all functions have the same precedence.

Named parameters

Arguments can be named when calling functions:

times ← # (number, factor) number × factor

3 times (factor: 4) – 12

It’s possible to give an external label to parameters, which will be used by the caller to label the arguments. In this case, the label is required:

times ← # (number, by factor) number × factor

3 times (by: 4) – 12
– won't compile: 3 times 4

An underscore as the label denotes that the parameter name is the label name:

times ← # (number, _ factor) number × factor

3 times (factor: 4) – 12

Named arguments allow a function with parameters that differ only in name:

greet ← # (to person) print-line “Hello, ‘person’!”
greet ⥆ # (from person) print-line “Greetings from ‘person’!”

greet(to: “Revi”) – Hello, Revi!
greet(from: “Livi”) – Greetings from Livi!

This is how the built-in range function works:

range(1, <: 5) – 1, 2, 3, 4
range(1, =: 5) – 1, 2, 3, 4, 5