10. Functions
This time, I will explain the function of LuneScript.
Function definition
LuneScript functions are defined like this:
// @lnsFront: ok
fn add_sub( val1:int, val2:int ): int, int {
return val1 + val2, val1 - val2;
}
print( add_sub( 1, 2 ) ); // 3, -1
The example above defines the following functions:
definition | ||
---|---|---|
function name | add_sub | |
First argument name | val1 | |
First argument type | int | |
Second argument name | val2 | |
Second argument type | int | |
primary return type | int | |
Secondary return type | int |
LuneScript can return multiple return values.
Return value
Function return values use the return statement.
Functions can return multiple values.
See below for multi-value return values.
Functions that do not return
Some functions do not return.
For example:
// @lnsFront: error
fn func(): __ {
while true {
}
}
func();
print( 1 ); // error
In this example, func()
is an infinite loop. Therefore, func()
will not return processing.
To make this explicit, the return type of func()
is __
. __
indicates that the function does not return.
This will tell us that the print()
statement following func()
is not processed and will result in an error.
Note that functions with a return type of __
must not return.
For example, if you break as follows, the loop will be exited, so the process will return from func()
. An error will occur in such cases.
// @lnsFront: error
fn func(val:int): __ {
while true {
if val == 1 {
break;
}
}
}
variable length arguments, return value
Variable length arguments and return values are available.
See the following article for details.
definition location
Functions can be defined anywhere a statement can be written. Specifically, you can define it inside a block like this:
// @lnsFront: ok
fn sub():int {
let mut val = 0;
{
{
fn func(): int {
return 1;
}
val = val + func();
}
fn func(): int {
return 2;
}
val = val + func();
}
fn func(): int {
return 3;
}
return val + func();
}
print( sub() ); // 6
Functions with the same name can be defined in different scopes.
public function
Functions, like variables, can be exposed externally using pub.
// @lnsFront: ok
pub fn func(): int {
return 1;
}
Specifying pub makes the function accessible from the outside.
global is also available.
// @lnsFront: ok
global fn func(): int {
return 1;
}
Global declarations of functions have the same restrictions as global declarations of variables.
"A function declared global becomes effective when the module that declares it is imported."
Exposing functions externally has the following restrictions:
"Functions exposed to the outside world must be declared at the topmost scope of the script"
form type
LuneScript can treat function objects as values. You can use form as a special function object type.
Here's an example of using form:
// @lnsFront: ok
fn test() {
print( "hoge" );
}
fn sub( func:form ) {
func();
}
sub( test ); // hoge
This example has the following configuration:
- Define a function test
- The function sub has an argument of type form
- Execute sub with test as argument
This will run test inside sub and print hoge .
In addition, the form type is treated as the following functions.
// @lnsFront: skip
fn func(...):... {}
A function type that can be assigned to a form type
As above, form is synonymous with fn func(...):... {}
.
Also, ...
represents zero or more stem!
.
This means that functions with arguments of type stem! are assignable to type form , and functions with arguments of non-stem! are unassignable.
If it can be assigned, the next call to func2( nil ) will call func( nil ), resulting in incorrect behavior.
// @lnsFront: error
fn func( val:int ) {
print( val + 1 );
}
let func2:form = func;
func2( nil );
Here are examples of substitutable and non-substitutable cases.
// @lnsFront: error
let form1:form = fn ( val1:stem! ) { };
let form2:form = fn ( val1:stem ) { }; // error
let form3:form = fn ( val1:stem!, val2:stem! ) { };
let form4:form = fn ( val1:stem!, val2:stem ) { }; // error
The above form1 and form3 are assignable, but form2 and form4 are not assignable.
form declaration
As mentioned above, only some types of functions can be handled by form.
To handle functions that cannot be handled by form, declare form as follows.
// @lnsFront: ok
form funcform( val:int ):int;
fn sub( func:funcform ) {
print( func( 1 ) + 1 );
}
sub( fn ( val:int ):int { return val + 1; } ); // 3
This example declares funcform as a form .
The form declaration makes funcform a function type with an int type val as an argument and an int type return value.
anonymous function
An anonymous function defines a function without a name.
Here is an example of an anonymous function:
// @lnsFront: ok
fn sub( func:form ) {
func( 1 );
}
sub( fn ( val:stem! ) { print( val ); } ); // 1
This example defines the anonymous function fn ( val:int ) { print( val ); }
.
By passing this anonymous function to the argument of sub()
, the anonymous function will be executed in sub()
.
An anonymous function declaration is an expression.
function call
Attaching ()
to a function object causes that function to be executed.
The types of function formal and actual arguments must match. Note that omitted actual arguments are treated as nil. It is an error if the dummy argument corresponding to the omitted actual argument is not nilable.
Omitting Arguments
Please check the following article about omitting arguments.
Function limits
LuneScript functions cannot be overloaded with different arguments.
summary
Summarizing the functions in LuneScript,
- Declare with fn
- can have multiple return values
- Can have variable length arguments and return values
- Publish functions to external modules with pub, global
- Function object type uses form type and form declaration
- have anonymous functions
- Omitted actual argument contains nil
- no function overloads
Next time, I will explain nilable.