module Functions {
// LAMBDAS
// use fn to define lambda functions
fn test1() => {
// define a variable used by lambda function
let y = 0;
// define lambda function
let f = fn(x : int) : int => {
y += 1; // lambda functions can access variables in scope
return x + y;
}
// invoke lambda function
let x = f(1);
}
// FUNCTION TYPES
// use typedef to define a function type
// define a callback function type with a single integer parameter.
// omitting tje return type means the function's return type is void
typedef IntCallback = fn(value : int);
fn test2() => {
// define lambda function
let f = fn(x : int) {
print(x);
}
// cast function to callback type
let f2 = f::IntCallback; // cast works because function signature matches
}
// USING FUNCTION TYPES WHEN DEFINING FUNCTIONS
// a function type can be assigned to a function implementation using fn::type
// when the type is assigned, the types of the parameters and return value
// do not need to be specified.
fn test3() => {
// define lambda function using callback function type
let f = fn::IntCallback(x) { // note parameter does not specify type
print(x);
}
}
// NAMED FUNCTIONS
// use fn to defined named functions, using same syntax as with lambdas
// the following function returns an incremented integer
fn inc(x: int) : int => x + 1;
fn test4() => {
// call function
let x = inc(1);
}
// VARIABLE NUMBER OF ARGUMENTS
// use ... to capture arguments as an array
// the following function returns the sum of it's arguments
fn sum(...numbers : int[]) : int => {
let value : int = 0;
for (number in numbers) {
value += number;
}
return value;
}
fn test5() => {
// call with regular args
let x1 = sum(1, 2, 3);
// use ... to flatten iterables into arguments
let x2 = sum(...[1, 2, 3]);
// can use ... along with regular arguments
let x3 = sum(1, ...[2, 3]);
}
// DEFAULT PARAMETER VALUES
// use = to specify default values for parameters
fn inc_with_default(x : int, inc_by : int = 1) => {
return x + inc_by;
}
fn test6() {
let x = 1;
x = inc_with_default(x); // increments by 1
x = inc_with_default(x, 2); // increments by 2
}
// OPTIONAL PARAMETER VALUES
// use an optional type and a none default value for optional parameters
fn inc_with_optional(x : int, inc_by : int? = none) {
if (inc_by) {
return x + inc_by!; // increment by value if specified
}
return x; // don't increment if parameter not specified
}
fn test7() {
let x = 1;
x = inc_with_optional(x); // increments by 1
x = inc_with_optional(x, 2); // increments by 2
}
// MULTIPLE RETURN VALUES
// use a tuple to return multiple return values. see tuples for more info.
fn return_2_ints(x : int, y : int) : (int, int) => {
return (x + 1, y + 1); // return tuple
}
fn test8() {
let x = return_2_ints(1, 2); // x is (2, 3)
}
// GENERIC FUNCTIONS
// use {T} after fn to define a generic function
fn generic_inc{T}(x : T) : T => x + 1::T;
fn test9() => {
// call generic function using explicit type parameter
let x1 = generic_inc{int}(1);
// call generic function using type parameter inference
// the type parameter (int) is inferred based on the type of the parameters (1)
let x2 = generic_inc(1);
}
}