-
Notifications
You must be signed in to change notification settings - Fork 0
Functions
In programming, a function is simply a reusable block of code. In Wi, functions are first-class citizens, meaning they can be stored in variables, passed as arguments to other functions, and returned from other functions.
In Wi, functions are expressions, so to define a function you need to declare a variable and define it with function expression:
var f = function() {
};Let's analyze what is what here.
-
(): this is the function's parameter list. A parameter is an input to a function. In this examplefhas no parameters. In this one, however:
var f = function(x) {
};It has a parameter called x.
-
{and}: this is the function body. It is defined by a block and has its own scope. Parameters are locals within that scope.
Executing a function is called calling it. To call a function, we use the call operator () which we discussed earlier. In case you forgot:
Call operator
()is used to call functions. It accepts arguments separated by,
Arguments are values that you pass into the function parameters.
For example, our good old function f. To call it, we need to pass a value to the parameter x:
var f = function(x) {
};
f(10);Here, 10 is the argument, x is the parameter. We pass 10 into x. If you don't pass enough arguments into a function, you will cause a runtime error:
var f = function(x) {
};
f();runtime error: expected 1 arguments but got 0
--> file.wi:4 in main function
A technical term for a function's accepted parameter count is arity.
Every function returns some value. Think of returning a value as the answer. You called a function, it answered with a value. Even if you don't specify one, Wi implicitly returns null from every function (the function has to answer our call). So if we were to print out the f example:
var f = function(x) {
};
print(f(10));We would see:
null
But we have a handy return statement, which accepts an expression to make our answer different:
var f = function(x) {
return x;
};
print(f(10));Now when we call our f, it answers with x, its parameter, and since we passed 10 into x we see:
10
return statement can also be used to stop some code from executing, for example:
var f = function(x) {
if (x == 4) {
return;
}
print(x);
};
f(4);
f(10);In this example, if the passed argument is 4, we won't print it. This program will output:
10
return without an expression will return null.
A function can call itself. This is called recursion.
Let's define a function to calculate the factorial of a number n using recursion:
var factorial = function(n) {
if (n <= 1) {
return 1;
}
return n * factorial(n - 1);
};
print(factorial(5)); // 120Let's analyze what's happening here.
When we call factorial(5), it checks if n is less than or equal to 1. This is a safeguard here to prevent infinite recursion - if we didn't have it, the function would call itself forever, eventually causing a stack overflow error. Since 5 is not <= 1, it returns 5 * factorial(4).
-
factorial(4)returns4 * factorial(3). -
factorial(3)returns3 * factorial(2). -
factorial(2)returns2 * factorial(1). -
factorial(1)hits the safeguard and returns1. Then the results "unwind":
factorial(5) = 5 * 4 * 3 * 2 * 1 = 120Recursion has limits. If you call a function too many times without returning, you'll cause a stack overflow:
var infinite = function() {
infinite();
};
infinite();The error message isn't pretty, but you'll definitely notice it.