Skip to content

Functions

Positron edited this page Aug 11, 2017 · 8 revisions

The function keyword is optional. If the function has no parameters, the void keyword is optional:

// These are all the same:
function void F( void ) {}
function void F() {}
void F() {}

For a function that returns a value, it is not necessary to have a return statement at the end of the function. As long as the function ultimately returns a value, you can nest the return statements:

// Get absolute value of number.
int Abs( int number ) {
   if ( number < 0 ) {
      return number * -1;
   }
   else {
      return number;
   }
}

A parameter can lack a name. You won't be able to use such a parameter, but you still need to pass an argument for it. This can be used to indicate a parameter is no longer used. This works for script parameters as well.

int Sum( int used1, int, int used2 ) {
   return used1 + used2;
}

script "Main" open {
   Print( d: Sum( 100, 0, 200 ) ); // Output: 300
}

In a function, the magic identifier, __FUNCTION__, is a string literal that contains the name of the current function:

void SomeFunc() {
   Print( s: __FUNCTION__ ); // Output: somefunc
}

__FUNCTION__ might look like a predefined macro, but it is not a macro. As a consequence, it cannot be used in string literal concatenation.

Optional parameters

A function parameter can have a default argument. If the user does not supply an argument for the parameter, the default argument will be used:

void Greet( str who = "Mate" ) {
   Print( s: "Hello, ", s: who, s: "!" );
}

script "Main" open {
   Greet( "Fine Fella" ); // Output: Hello, Fine Fella!
   Greet();               // Output: Hello, Mate!
}

Builtin functions now support default arguments that are strings. This means you can use MorphActor() with a single argument, as is allowed by the wiki page, and it will work as intended:

script "Main" enter {
   // These are the same:
   MorphActor( 0, "", "", 0, 0, "", "" );
   MorphActor( 0 );
}

Nested functions

A function can be declared inside a script or inside another function. Such a function is called a nested function:

script "Main" open {
   void Greet() {
      Print( s: "Hello, World!" );
   }
   Greet(); // Output: Hello, World!
}

Functions can be nested arbitrarily deep:

script "Main" open {
   void F1() {
      Print( s: "F1()" );
      void F2() {
         Print( s: "F2()" );
         void F3() {
            Print( s: "F3()" );
         }
         F3();
      }
      F2();
   }
   F1();
}

A nested function can access the local variables located outside of it:

script "Main" open {
   str msg;
   void ShowMsg() {
      Print( s: msg );
   }
   msg = "Hello, World!";
   ShowMsg(); // Output: Hello, World!
   msg = "Goodbye, World!";
   ShowMsg(); // Output: Goodbye, World!
}

Nested functions can have auto as the return type. The compiler will deduce the return type from the returned value. If no value is returned, the return type will be void:

strict namespace {

script "Main" open {
   auto F1() {} // Same as: void F1() {}
   auto F2() { return; } // Same as: void F2() {}
   auto F3() { return "abc"; } // Same as: str F3() {}
}

}

Passing around a reference to a nested function is not allowed at this time.

Technical details

Be aware when calling a nested function that has a lot of local variables. The compiler generates code to save and restore local variables. This might be too much a penalty for performance critical code.

Calling a nested function recursively too many times will eventually crash the game.

Function literals

Syntax
( return-type parameter-list ) { [statements] }

You can declare and call a nested function at the same time. Such a nested function is called a function literal:

script "Main" open {
   Print( s: "Sum: ", d: ( auto() ) {
      int sum = 0, i = 1;
      while ( i <= 10 ) {
         sum = sum + i;
         ++i;
      }
      return sum;
   }() ); // Output: Sum: 55
}

The above code is equivalent to the following code:

script "Main" open {
   auto CalculateSum() {
      int sum = 0, i = 1;
      while ( i <= 10 ) {
         sum = sum + i;
         ++i;
      }
      return sum;
   }
   Print( s: "Sum: ", d: CalculateSum() ); // Output: Sum: 55
}