Functions
Function syntax in Move is shared between module functions and script functions. Functions inside of modules are reusable, whereas script functions are only used once to invoke a transaction.
#
DeclarationFunctions are declared with the fun
keyword followed by the function name, type parameters, parameters, a return type, acquires annotations, and finally the function body.
For example
#
VisibilityModule functions, by default, can only be called within the same module. These internal (sometimes called private) functions cannot be called from other modules or from scripts.
To allow access from other modules or from scripts, the function must be declared public
#
NameFunction names can start with letters a
to z
or letters A
to Z
. After the first character, function names can contain underscores _
, letters a
to z
, letters A
to Z
, or digits 0
to 9
.
#
Type ParametersAfter the name, functions can have type parameters
For more details, see Move generics.
#
ParametersFunctions parameters are declared with a local variable name followed by a type annotation
We read this as x
has type u64
A function does not have to have any parameters at all.
This is very common for functions that create new or empty data structures
#
AcquiresWhen a function accesses a resource using move_from
, borrow_global
, or borrow_global_mut
, the function must indicate that it acquires
that resource. This is then used by Move's type system to ensure the references into global storage are safe, specifically that there are no dangling references into global storage.
acquires
annotations must also be added for transitive calls within the module. Calls to these functions from another module do not need to annotated with these acquires because one module cannot access resources declared in another module--so the annotation is not needed to ensure reference safety.
A function can acquire
as many resources as it needs to
#
Return typeAfter the parameters, a function specifies its return type.
Here : u64
indicates that the function's return type is u64
.
Using tuples, a function can return multiple values
If no return type is specified, the function has an implicit return type of unit ()
. These functions are equivalent
script
functions must have a return type of unit ()
As mentioned in the tuples section, these tuple "values" are virtual and do not exist at runtime. So for a function that returns unit ()
, it will not be returning any value at all during execution.
#
Function bodyA function's body is an expression block. The return value of the function is the last value in the sequence
See the section below for more information on returns
For more information on expression blocks, see Move variables.
#
Native FunctionsSome functions do not have a body specified, and instead have the body provided by the VM. These functions are marked native
.
Without modifying the VM source code, a programmer cannot add new native functions. Furthermore, it is the intent that native
functions are used for either standard library code or for functionality needed for the given Move environment.
Most native
functions you will likely see are in standard library code such as Vector
#
CallingWhen calling a function, the name can be specified either through an alias or fully qualified
When calling a function, an argument must be given for every parameter.
Type arguments can be either specified or inferred. Both calls are equivalent.
For more details, see Move generics.
#
Returning valuesThe result of a function, it's "return value", is the final value of it's function body. For example
As mentioned above, the function's body is an expression block. The expression block can sequence various statements, and the final expression in the block will be be the value of that block
The return value here is double_x + double_y
return
expression#
A function implicitly returns the value that its body evaluates to. However, functions can also use the explicit return
expression:
These two functions are equivalent. In this slightly more involved example, the function subtracts two u64
values, but returns early with 0
if the second value is too large:
Note that the body of this function could also have been written as if (y > x) 0 else x - y
.
However return
really shines is in exiting deep within other control flow constructs. In this example, the function iterates through a vector to find the index of a given value:
Using return
without an argument is shorthand for return ()
. That is, the following two functions are equivalent: