A Dana program is typically composed of a set of components, where each component has a set of functions which do different things. Components will often have some functions that implement interface function prototypes, and can be called from other components, and some utility functions which are local and not accessible from outside the component.
The way in which these two kinds of function are declared and called is broadly the same. The below code shows an example with one interface-implementing function, and one local function:
component provides App requires io.Output out, data.IntUtil iu {
int square(int i)
{
return i * i
}
int App:main(AppParam params[])
{
int v = iu.intFromString(params[0].string)
int result = square(v)
out.println("answer: $result")
return 0
}
}
All functions (except for constructors) have a return type, which may be void
for no return value, and have zero or more parameters each with a type and a name.
All functions can declare optional parameters using the opt
keyword. These parameters do not need to have a value set by the caller, but may carry useful extra information in some scenarios.
Let's imagine we have a power
function which raises a parameter to a given power:
int power(int i, opt int p)
{
return i * i
}
Here the raise-to-power parameter p
is declared as optional, so the caller does not have to pass a value for this parameter:
int r = power(4)
If we do want to pass a value to that optional parameter we simply include it in the call as any other parameter:
int r = power(4, 6)
For functions that have multiple optional parameters, we can also indicate which one we want to set by using its name:
int r = power(4, p = 6)
The function implementation can use the isset
operator to determine whether or not an optional parameter was given a value by the caller:
int power(int i, opt int p)
{
if (isset p)
{
//use a specific power, given by p
}
else
{
return i * i
}
}
```