One important difference to C is, that in EScript functions are first class objects and that they don’t have a name. Functions are defined with the fn
keyword and because a function is just another object, the definition is a statement and therefore it must end with a semicolon.
var square = fn(num) {
return num * num;
}; // don't forget this semicolon!
var a = square(5);
outln( a ); // Outputs: 25
Recursion
Remember local variables are only visible inside the surrounding scope, but excluding nested functions. Therefore the following code wouldn’t work, because the factorial
variable is not visible inside the function.
var factorial = fn(Number x){
if(x>1)
return x*factorial(x-1); // Warning: Variable 'factorial' not found
return x;
};
out( factorial(4) );
To overcome this issue you must define the factorial variable static or you can use the special thisFn
keyword, which is a reference to the current function:
var factorial = fn(Number x){
if(x>1)
return x*thisFn(x-1);
return x;
};
out( factorial(4) ); // Output: 24
Type Restrictions
The parameters of a function can be restricted to specific types. An exception is thrown if the type does not match.
var square = fn(Number num) {
return num * num;
};
square(5); // ok
square("foo"); // runtime error
It is also possible to allow multiple types for a single parameter. Furthermore it is important to know, that void is an independent type!
var print = fn([Number, String] value) {
outln(value);
};
print(42); // ok
print("foo"); // ok
print(void); // runtime error
var print2 = fn([Number, String, void] value) {
outln(value);
};
print(void); // ok
Default Values
Parameters can have default values. If a type restriction is specified, the default value must also be of that type!
var print = fn(value = "no value") {
outln(value);
};
print("hello"); // Output: hello
print(); // Output: no value
var print2 = fn(String value = void) {
outln(value);
};
print2(); // runtime error
Varargs
The last parameter of a function definition can be used for a variable argument list. The function can then accept arbitrary many values that are stored as an array in the last parameter.
var sum = fn( numbers... ) { // all arguments are automatically passed as an array
var sum = 0;
foreach( numbers as var n)
sum += n;
return sum;
};
outln( sum( 10,100,1000,4 ) ); // Output: 1114
Multiple Return Values
EScript does not support multiple return values directly, but it has some syntactic sugar to automatically assign multiple values to the content of an array: [ lValue* ] = Array
var calc = fn() {
return [17, 42]; // returns an array
};
[var a, var b] = calc();
outln("a:", a, " b:", b); // Output: a:17 b:42
Parameter Binding
You can set the first parameters of a function to fixed values by using a so called function binder (FnBinder): Array => Function
The result of this expression is a FnBinder object that is used as a wrapper around the function. You can use this object like a normal function, but it will always call the underlying function with the first parameters fixed:
var myFun = fn(a, b, c) {
out("a:", a, "b:", b, " c:", c );
};
myFun(1, 2, 3); // Output: a:1 b:2 c:3
// create a wrapper that always passes 100 and 200 as the first two parameters
var myBoundFun = [ 100, 200 ] => myFun;
myBoundFun( 300 ); // Output: a:100 b:200 c:300
Furthermore the FnBinder is used to combine an object with a function: Object -> Function
The result of this expression is again a FnBinder object. The bound object will be the this
object of the function.
var print = fn() {
outln(this);
};
print(); // Output: void
var boundedPrint = 42 -> print;
boundedPrint(); // Output: 42