1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180
|
Functions
=========
Introduction
------------
Functions are blocks of code that you can reuse throughout your program. They may receive input parameters and they always output something. The syntax is as follows:
```
fun function_name(param_1, param_2, param_3, ..., param_n)
{
// block of code
// to be executed
}
```
Functions may be associated to objects. Any function associated to an object may be used (called) by the object itself or by other objects. This means that functions are *public* (they are visible to the outside world).
**Note:** functions must be defined after the states.
Return statement
----------------
Use the `return` statement to stop executing the function and to return some value to the caller. Example:
```
// This function will return the double of input parameter x
fun double(x)
{
return 2 * x;
Console.print("This line will never be executed.");
}
```
If no value is specified after the `return` keyword, the function will be stopped and its return value will be `null`. Additionally, if no `return` statement is found, then the return value will also be `null`.
**Note**: an object state may also contain one or more `return` statements to stop the execution of its code. However, return values must not be specified in that context, since states do not return values.
Simple example
--------------
In the example below, we have an object called `Calculator` with two functions: `greet()` and `sum()`. `greet()` takes no input parameters and just greets the user. On the other hand, `sum()` takes two input parameters, `a` and `b`, and returns the sum `a + b`:
```
object "Calculator"
{
fun greet()
{
Console.print("Hello! I am a Calculator!");
}
fun sum(a, b)
{
return a + b;
}
}
```
In function `sum()`, variables `a` and `b` hold the input data and are only visible inside the function.
Now, let's create a program that uses this `Calculator`. Remember that the functions defined above can be called by any object, including `Application`:
```
object "Application"
{
calculator = spawn("Calculator");
state "main"
{
// greet the user
calculator.greet();
// do some computation
result = calculator.sum(5, 7);
Console.print(result);
// we're done!
Application.exit();
}
}
```
The output of the above program is:
```
Hello! I am a Calculator!
12
```
Notice that the `Application` does not need to know *how* the functions of the `Calculator` are implemented. It just needs to know *what* they do. This means that you may change the implementation of the `Calculator` without changing the `Application`, and the end-result will stay the same.
Recursive functions
-------------------
In SurgeScript, a function is said to be **recursive** when it calls itself within its code. Recursion can be useful in many ways; namely, when you define a problem in terms of itself. In mathematics, the factorial of a non-negative integer number `n`, denoted as `n!`, is such an example:
```
n! = { n * (n-1)! if n > 1
{ 1 otherwise
```
One interesting example of recursion that arises in computer science is called the *binary search* algorithm. Given a sorted [Array](/reference/array), the binary search finds the position of a target value without having to inspect the whole collection. In the example below, `bsearch()` is a recursive function:
```
object "Binary Search"
{
// Given an array sorted in ascending order, find()
// finds the position of the target value in the array.
// It returns its index, or -1 if the target is not found.
fun find(array, value)
{
return bsearch(array, value, 0, array.length - 1);
}
// Performs a binary search in array[start..end]
fun bsearch(array, value, start, end)
{
// get the middle point
mid = start + Math.floor((end - start) / 2);
// compare the middle point to the target value
if(start > end)
return -1; // target not found
else if(value == array[mid])
return mid; // found the target value
else if(value < array[mid])
return bsearch(array, value, start, mid - 1);
else
return bsearch(array, value, mid + 1, end);
}
}
```
Recursive functions must have at least one base case. A base case is a scenario that does not need recursion to solve the problem. In the factorial example, the base case is `n <= 1` (the factorial is 1). In the binary search example, the base case is `start > end`, meaning that the array is empty and the target value cannot be found, or `value == array[mid]`, meaning that the target value has been found at `mid`.
A sage once said: *"to understand recursion, you must first understand recursion."*
Constructors and destructors
----------------------------
In SurgeScript, constructors and destructors are special functions that are called whenever objects are created and destroyed, respectively. It's not mandatory to define them, but it may be useful to do so (you may want to set up things in your constructors, for example). Neither may receive any arguments (to set up objects with parameters, take a look at [chaining](/tutorials/advanced_features#chaining)).
Let's take our `Calculator` again. In the following example, `constructor()` is called automatically whenever a `Calculator` object is created. Likewise, `destructor()` is called automatically when the object is destroyed.
```
object "Calculator"
{
fun constructor()
{
Console.print("Creating a Calculator...");
}
fun destructor()
{
Console.print("Destroying a Calculator...");
}
fun greet()
{
Console.print("Hello! I am a Calculator!");
}
fun sum(a, b)
{
return a + b;
}
}
```
Now, if we run the `Application` of the previous section without any modification, the output of the program will be:
```
Creating a Calculator...
Hello! I am a Calculator!
12
Destroying a Calculator...
```
Note that, for any object, its `constructor()` runs *before* its main state.
|