In computer programming a function is a sequence of instructions that perform a specific task. In AskiaScript, you can define your own custom functions to make your code more robust, readable and maintainable. By writing a function to handle a repeated task, you reduce the chances of errors in your code, as you only need to write the code that handles that task once, and maintenance for that task only needs to be done on this one section of code (i.e. in the function).
This topic provides a detailed technical description of functions in AskiaScript. For a general introduction and overview of functions, please see our blog post Of Askia Scripts and Functions.
In this topic:
In Askia software, functions are defined in the resource file (ASX). Each function should be part of a module. The default way to create a module is with Module XX / End Module. You can have more than one .ASX file in a survey.
To use a module in a routing, you need to call Import followed by the name of the module. Some of the variables and functions will be available from outside the module; they will need to be marked as Export.
By default, every parameter is passed by value (except arrays, and future objects if they happen), but you can specify by value or by reference explicitly with the keywords ByVal and ByRef respectively.
Every object created is global. If you declare a variable outside a For loop, an If block, or a function, it will be accessible everywhere.
AskiaScript is derived and has a different context according to the application you are using. This is because there are different locations, depending on the context in which AskiaScript is being used:
Functions are stored in the QES file as resources (.ASX).
A module is declared with the keyword Module and ended with the End Module or EndModule. You can have more than one .ASX file in a survey and you can have more than one module in a .ASX file. To use a module in a routing, you need to call Import followed by the name of the module. You cannot nest modules.
Module <Name of the module> <Body of the module> End Module
A function is declared with the keyword Function and ended with the End Function or EndFunction. To make the function available outside the module (i.e. so that it can be used/called from outside the module), you need to start with Export.
You cannot nest functions.
Module <Name of the module>
Function <Name of the function1> ( <List of parameters> ) <Return type>
<Body of the function1>
End Function
Export Function <Name of the function2> ( <List of parameters> ) <Return type>
<Body of the function2>
End Function
End Module
Here, only function2 will be available outside the module, as it is the only one using the Export keyword..
Module MyMath
' Increment the number in parameter
Export Function Increment(nbr As Number) As Number
Return nbr + 1
End Function
' Decrement the number in parameter
Export Function Decrement(nbr As Number) As Number
Return nbr - 1
End Function
End Module
To use a module in a routing instruction, you need to call Import followed by the name of the module. Then you can call a function by starting with the module name followed by two colons "::" and followed by the function name:
Import MyMath dim i = 0 i = MyMath::Increment(i) ' -> i = 1 i = MyMath::Increment(i) ' -> i = 2 i = MyMath::Decrement(i) ' -> i = 1
You can call a function from within a module (.ASX file), without needing to specify the module name:
Module ABC
Function Increment As Number
End Function()
Dim j
Increment(j) ' Allowed
end Module
You cannot call a function which is defined in a ASX file outside the ASX file without using the module name:
dim i = 0
i = Increment(i) 'Not allowed, module name missing
You cannot call a function before it has been defined:
dim i = 0
Increment(i) 'Not allowed, Increment is not defined here because the definition of the function is below Function Increment() As Number End Function
You cannot write a script which uses functions on several rows:
dim i = 0
'Not allowed: Increment(i) + Increment(i)
'But the following script is allowed:
Increment(i)
Increment(i)
↑ Top of page ↑
The name of the module is declared just after the keyword Module. It:
The name of the function is declared just after the keyword Function. It:
The function name must be followed by parentheses, even if there are no parameters, as follows:
Function MyFunction() As Number
Most of the time, a function will return a value. To minimise the chance of errors, and because AskiaScript is strongly typed, you should declare the function's return type whenever the function returns a value. To do so, after the name of the function and the parenthesis, use the keyword As follow by the type of the value, as follows:
Function MyFunction() As Number
Because some functions do not always return a value, the function type is optional.
The allowed types are:
"In computer programming, a parameter is a special kind of variable, used in a function to refer to one of the pieces of data provided as input to the function.
These pieces of data are called arguments. An ordered list of parameters is usually included in the definition of a function, so that, each time the function is called, its arguments for that call can be assigned to the corresponding parameters." - Wikipedia
In AskiaScript:
For example:
Function MyFunction(param1 As Number, param2 As String, optionalParam3 As Number = 0) As Number
To minimise the chance of errors, and because AskiaScript is strongly typed, the parameter must have a specific type. To do so, after the name of the parameter, use the keyword As, followed by the type of the expected value, as in the following example:
Function MyFunction(stringParam As String, arrayParam As StringArray, numberParam As Number) As Number
The allowed types are:
When calling a function, you must assign a value for each parameter in the right order. In certain cases, it could be very useful to omit the value for a given parameter. In that case, you may specify a default value to make the parameter optional. As in many languages, all optional parameters must be specified after all mandatory parameters:
' This is illegal syntax: Function MyBadFunction(optionalParam As Number = 0, requiredParam As String) As String ' ... body of the function End Function
Function MyGoodFunction(requiredParam As string, optionalParam As Number = 0) As String ' .... body of the function End Function
In computer programming, you can pass parameters by value or by reference. In Askia, every parameter is by default passed by value, except for arrays, unless explicitly specified by ByVal and ByRef keywords.
When a parameter is passed by value, the value assigned to the parameter is a local copy of the initial value in the variable. This means that modifying the parameter will not modify the initial variable. As in many languages, in AskiaScript all primitives (Number, String and Date) are passed by value, as follows:
' Functions Export Function TestParameterByVal(i as Number) As String dim str = "rn--- Inside the function: i = " + i i = i + 1 str = str + "rn--- After increment, inside the function: i = " + i Return str End Function ' Usage in routings Import MyModuleName
Dim i = 1 Dim output = "Before the function: i = " + i output = output + MyModuleName::TestParameterByVal(i) output = output + "rnAfter the function: i = " + i ' Produce the following output: ' 'Before the function: i = 1 '--- Inside the function: i = 1 '--- After increment, inside the function: i = 2 'After the function: i = 1
When a parameter is passed by reference, it is treated as a reference (or pointer) to the initial variable itself. This means that modifying the variable parameter will modify the value in the initial variable. As in many languages, in AskiaScript all complex objects (Arrays, Question, Response ...) are passed by reference, as follows:
' Functions
Export Function TestParameterByRef(arr as NumberArray) As String
dim str = "rn--- Inside the function: arr = " + arr.Join(", ")
arr.Insert(3)
str = str + "rn--- After insertion, inside the function: arr = " + arr.Join(", ")
Return str
End Function
' Usage in routings
Import MyModuleName
Dim arr = {1; 2}
Dim output = "Before the function: arr = " + arr.Join(", ")
output = output + MyModuleName::TestParameterByRef(arr)
output = output + "rnAfter the function: arr = " + arr.Join(", ")
' Produce the following output:
'
'Before the function: arr = 1, 2
'--- Inside the function: arr = 1, 2
'--- After inserting, inside the function: arr = 1, 2, 3
'After the function: arr = 1, 2, 3
The function body is all the code between the keywords Function and End Function (or EndFunction). This may consist of any legal AskiaScript code. If the function has a specific type, all paths of the function must always return the specified type.
' Illegal function syntax: some paths doesn't return the specified type
Export Function MyBadFunction(testValue As Number) As Number
If testValue < 10 Then
Return 1 ' This path is correct, it return a number
Else If testValue >= 10 And testValue < 20 Then
Return "hello" ' This path is incorrect, it return a string instead of number
Else If testValue >= 20 And testValue < 30 Then
Return ' This path is incorrect, it doesn't return a number
End If
' This path is incorrect: if the testValue is greater than 30, it doesn't return anything
End Function
' Legal function syntax: all paths return the specified type
Export Function MyBadFunction(testValue As Number) As Number
If testValue < 10 Then
Return 1 ' This path is correct, it return a number
Else If testValue >= 10 And testValue < 20 Then
Return 2 ' This path is correct
Else If testValue >= 20 And testValue < 30 Then
Return 3 ' This path is correct
End If
' This path is correct: if the testValue is greater than 30, it returns a number
Return 0
End Function
As in all programming languages, all variables declared in the body of the function are only available inside that function; they are not visible outside the function.
In the body of the function, you can access variables available in the global scope (except Action), but you cannot access variables that are within a different local scope (e.g. local to a different function). If you want to access the value of a variable within a different local scope, then you must pass it as a function parameter.
' Function Export Function LocalScopeTest() As String Dim i = 20 Return "rn--- Inside the function i = " + i End Function ' Usage in routings Dim i = 10 Dim output = "Outside the function i = " + i output = output + MyModuleName::LocalScopeTest() output = output + "rnAfter the function invocation i = " + i Return output ' This code produce: ' ' Outside the function i = 10 ' --- Inside the function i = 20 ' After the function invocation i = 10