Difference between revisions of "Function Reference"

From the CreationKit Wiki
Jump to navigation Jump to search
imported>DayDreamer
m (→‎Bugs: value returning -> typed)
imported>JLundin
(→‎Calling Functions: Removing confusing and erroneous information about properties)
Line 105: Line 105:


Calling a function simply involves using the function's [[Identifier Reference|identifier]], followed by parenthesis, and any parameters that the function takes. The return value of the function is the result of the function call and can be assigned to a variable, or used to call another function or property.
Calling a function simply involves using the function's [[Identifier Reference|identifier]], followed by parenthesis, and any parameters that the function takes. The return value of the function is the result of the function call and can be assigned to a variable, or used to call another function or property.
If you are calling a function from outside the current script or script fragment, note that no properties defined in the function's own script will be valid when it is called. Therefore you must pass any properties you wish to use in the function as parameters, defined in the calling script.


If you are calling a global function and the function's owning script isn't the current script or isn't [[Script File Structure#Imports|imported]], then you must prefix it with the name of the script the function resides in.
If you are calling a global function and the function's owning script isn't the current script or isn't [[Script File Structure#Imports|imported]], then you must prefix it with the name of the script the function resides in.

Revision as of 15:58, 13 August 2013

Functions are units of work that are larger than a single expression, and may take various parameters and return a value to their caller.

Function Definition

<function> ::= <function header>
               [<function block>
               'endFunction']

Function headers must always be followed by a block and an "EndFunction" keyword, unless they are native functions (which are exposed by the game).

Function Header

<function header> ::= [<type>] 'Function' <identifier> '(' [<parameters>] ')' ('global' | 'native')* <flags>*

A function header starts (optionally) with the return type of the function, and is then followed by the name of the function, its parameters (if any), and any modifiers and flags.

The identifier used to name the function cannot conflict with any other function in the current script. If the identifier matches a function in the parent script, then the return type and parameters much match the parent script's version of the function - and the function will override the parent's function.

The "Global" flag indicates a function that does not actually run on an in-game object, and has no "Self" variable.

The "Native" flag indicates a function that does not have a function body, because the function is implemented by the game itself. If you add the native flag to a function the game does not expose, the compiler won't complain, but the game will error at you. The same flag cannot be specified more then once.

InDepth.jpg


The "self" variable is a natural consequence of object oriented programming. Object oriented programming relies on the concept of an abstract class and an instance of that class (An instance may also be called an object.)

The relationship between a class and an instance is similar to the difference between a blueprint of a car and the actual car that is made from that blueprint. A single blueprint may be the basis for many cars. The blueprint is an abstraction. You cannot interact act with it. For example, you can't turn on the radio of the car in the blueprint. It's a piece of paper. In order to turn on the radio, you need to interact with the actual car. The blueprint is the class, and the car is the object. The way you find out which object is being acted upon by a function is to refer to the self. For example, self.TurnOn(theRadio) will turn on the radio of the car that calls that function, and only that one car.

All functions are actually resolved by the compiler to use the this/self pointer. If a script changes an integer variable someInt to 5, what it looks like to us is: someInt = 5. Internally, that variable is labeled with, and considered a component of, the object that calls it, which could be written as self.someInt = 5

A simple example: imagine a function invoked on an object that takes a parameter that points to another object of the same class: car1.Ram(car2) (which should ram your car into another car). Obviously, the car cannot ram itself. By using the "Self" variable, we can ensure that car2 is not equal to Self and prevent damaging or unnecessary code from executing:

;The function is called on one car like this.
Car1.Ram(car2)

;Then we write the function:
function Ram(object someVehicle)

;if someVehicle is the same as the car that the function was initially called on,
;kill the function and do not proceed to ram it.
 if(someVehicle == self)
    return
 else
    self.Moveto(someVehicle)
 endIf
endFunction


Another example is a script that is trying to release an object it no longer needs so that the reference no longer consumes memory. However due to the its complexities, the script may accidentally end up referencing the same object. A reference to an object that was expected to be released is called a dangling pointer, and it can cause crashes or other problems as the application progresses. By comparing newObject to Self (if(newObject != Self)), we can be sure that when the old object is released it will be properly replaced by newObject.

Parameters

<parameters> ::= <parameter> (',' <parameter>)*
<parameter>  ::= <type> <identifier> ['=' <constant>]

The parameter list is a comma-separated list of types and identifiers that indicate the various parameters that a function takes. Each parameter may be optionally followed by an equals sign and a constant, which indicates that the parameter has a default value. If a parameter has a default value, every parameter after it must also have a default value.

Parameters are essentially variables the function has access to that the caller gives initial values to.

Function Block

<function block> ::= <statement>*

The function block contains zero or more statements. This performs the actual work of the function.

Examples

; A simple function that adds the two values together and returns the result
; Global, because it doesn't need a self variable
int Function AddTwo(int a, int b) global
  return a + b
endFunction


; A function that increments a value on this script by the specified amount.
; The amount has a default value of 1 (so the caller doesn't have to pass it)
Function IncrementValue(int howMuch = 1)
  myValue += howMuch
endFunction

Special Variables

There are two special variables in a function, but only in a non-global one. "Self" refers to the instance of the script that the function is running on, and is useful if you want to pass yourself as a parameter to another function somewhere else.

"Parent" is only used to call a parent script's version of a function, in the case where you extend the parent.

Examples

; Pass our self off to another function
SomeObject.OtherFunction(self)


; Call the parent's version of DoStuff, ignoring our local definition
Parent.DoStuff()

Calling Functions

Global function:

[<identifier> '.'] <identifier> '(' [<parameters>] ')'

Non-global function:

[<expression> '.'] <identifier> '(' [<parameters>] ')'

Calling a function simply involves using the function's identifier, followed by parenthesis, and any parameters that the function takes. The return value of the function is the result of the function call and can be assigned to a variable, or used to call another function or property.

If you are calling a global function and the function's owning script isn't the current script or isn't imported, then you must prefix it with the name of the script the function resides in.

If you are calling a non-global function and it isn't on yourself, then you must prefix it with the object you want to call it on.

Parameters

<parameters> ::= <parameter> (',' <parameter>)*
<parameter>  ::= [<identifier> '='] <expression>

The parameter list is a comma-separated list of expressions in the same order as the parameters are listed in the function definition. If a parameter is optional, it does not have to be passed (the default value is inserted by the compiler into the call location). You may specify parameters out of order by prefixing the expression with the identifier of the parameter (matching the name of the parameter in the definition) followed by an equals sign.

Examples

; Call the function: MyFunction(int a, int b) and get the result and put it in x
x = MyFunction(1, 2)


; Call the function DefaultFunction(float a, float b, float c = 0.0, float d = 1.0) on MyObject,
; but only pass in the first three parameters
MyObject.DefaultFunction(4.0, 2.0, 1.0)


; Call the function DefaultFunction(float a, float b, float c = 0.0, float d = 1.0), but specify
; argument d out of order because we want c to keep the default it has
DefaultFunction(5.0, 2.4, d = 2.0)


; Call the global function MyGlobal() in the Utility script
Utility.MyGlobal()

Notes

  • The nomenclature of Bethesda's functions' arguments is consistent, prefixing argument names such that their nature is easily determined. The naming convention is as follows, each prefix denoting the corresponding qualities:
a : Argument :: b : Bool :: f : Float :: i : Int :: p : Pointer :: s : String :: k : Form/Alias :: u : Unsigned
auiCount, for instance, is an unsigned integer argument while asFileName is a string argument. Note that 'p' and 'k', for Papyrus' purposes, are interchangeable and that Papyrus does not actually have pointers.

Bugs

  • In typed functions, the compiler does not properly check all code paths for returns with values. If the function exits without providing a return value, the result is indeterminate and causes unexplained failures throughout related scripts (possibly due to stack corruption).


Language: [[::Function Reference|English]]  • [[::Function Reference/fr|français]]