Tutorial; Functions - HWRM/KarosGraveyard GitHub Wiki

Functions

Functions are "self contained" modules of code that accomplish a specific task. Once a function is written, it can be used over and over and over again. Functions can be "called" from the inside of other functions.

'Pure' functions "take in" data, process it, and "return" a result, without doing anything else. A function which has one or more 'side effects' (perhaps like printing something to a log file in the background) are not 'pure'.

Scripts for HWRM need to make use of the predefined stock functions to do anything.

💡 Make good use of the wiki's search features to find functions. Avoid the 'reference' pages, as these are not being maintained.

There are maaany such functions, most of which are prefixed indicating their usage:

  • SobGroup_ functions deal with SobGroups
  • Player_ functions deal with Players
  • Several others, such as Selection_ or MainUI_

Also included are a significant amount of Lua functions, such as print, random, tostring, and so on.

If you pass the wrong amount of arguments to a function, or they are of the wrong type(s), the running script will crash (the game will keep running just fine, only the script will break).

You can write your own functions of course:

-- custom function taking two arguments
function myFunction(arg1, arg2)
  -- using stock functions 'print' (to print to log) and 'tostring' (to convert args to strings if they arent already)
  print(tostring(arg1) .. ", " .. tostring(arg2));
end

-- call it
myFunction(10, "hello"); -- '10, hello' will appear in `HwRM.log`

Functions are especially relevant to perform tasks which will appear many times in your code:

function add(a, b)
  return a + b;
end

add(1, 4); -- 5
add(7, -3); -- 4
add(add(1, 2), 5); -- 8

Returning

The return keyword is used to exit a function at a specific point. A function may return nothing (nil), or one or more values (like our add function returns a number).

function foo()
  local rand = random(); -- random value between 0 and 1
  if (rand < 0.5) then
     return "a", "b", 10;
  end
end

-- either "a", "b", 10
-- or nil, nil, nil
a, b, c = foo();

In the above case, the function foo has a 50% chance to return three values ("a" "b" and 10). If this chance doesn't occur, it implicitly returns nil (which is what any function with no explicit return statement returns on its last line).

Functions As Variables

Functions are 'first class' entities in Lua, meaning you can store them in variables and pass them around:

-- store the function reference in 'my_fn'
local my_fn = function()
end

doSomethingElseThenCall(my_fn);

Keep in mind that the value stored in my_fn is the memory address of the function, not the function itself. As such, functions are also 'reference types', along with tables and userdata.

arg and Variadic Functions

A variadic function is a function with a variable amount of arguments.

Usually, a function statement defines the function's parameter list literally. However, there is a special syntax ..., which acts as a 'catch all' parameter:

fixed = function (a, b)
  -- this function with two defined params, and no more
end

variadic = function (a, b, ...)
 -- this function with two defined params, and one OR MORE extra arguments
end

The unbounded list of arguments which are caught by the ... are stored in an implicit parameter, arg:

-- f is a function which prints the number of 'extra' arguments it received
f = function (a, b, ...)
  print(getn(arg));
end

f(); -- prints nil
f(1, 2); -- stil nil, a and b are fixed arguments so not included in `arg`
f(1, 2, 3); -- 1
f(1, 2, 3, 4, 5, 6); -- 4

A function can have only extra arguments and no fixed ones:

function (...)
  -- arguments on `arg`
end

Methods

Tables have a special syntax for functions which are considered 'methods' of the table:

my_thing = {
  val = 10,
};

function my_thing:doSomething()
  print("table val is " .. tostring(self.val));
end

my_thing:doSomething();

A method is defined and invoked using the colon access operator (:) as opposed to the regular dot (.).

A table method always has an implicit first parameter, self. This is just the table which hosts the method being called.

If you call a method with normal dot syntax, the self parameter is not supplied:

my_thing = {
  ["val"] = 10,
};

-- there is an invisible first parameter, 'self', which is typically the host table ('my_thing' in this case)
function my_thing:doSomething()
  print("table val is " .. tostring(self.val));
end

my_thing:doSomething(); -- prints as expected
my_thing.doSomething(); -- error, 'self' is nil
my_thing.doSomething(my_thing); -- same as the first call using colon syntax

my_other_thing = {};
my_thing.doSomething(my_other_thing); -- we can get rather arcane and start redefining the semantic meaning of 'self', but its almost always not a good idea

You can write this without the fancy syntax of course:

my_thing = {
  ["val"] = 10,
};

function doSomething(tbl)
  print("table val is " .. tostring(tbl.val));
end

doSomething(my_thing);

This just means the function is 'free', as in it is not associated with any particular table.

See Also

  • First Steps for an introduction to modding in general.
  • Custom Coding for an introduction to custom scripting for ships