Websites Navigation: Airbit | Shop | m-shell.net
Languages: EN | DE

Functions

Functions are a way to write repeatedly occuring computations only once, but use them wherever needed. They also help in structuring longer scripts into smaller, easily understandable units. By putting often occuring functions into separate modules (see section * ()), function libraries can be created.

Functions normally have a set of parameters as input and return a single function result as output. Since the function result can be an array, an arbitrary number of values can be returned.

The function is left by returning a value with a return statement. If the function is left by reaching its end, null is returned.

The following example declares a function sqrt computing the square root of a number x greater than or equal to 1, then calls it with parameters x=2 and x=9:

function sqrt(x)
  y=x;
  do
    y0=y; y=(y+x/y)/2
  until y>=y0;
  return y
end // of function sqrt

print sqrt(2), sqrt(9)
→ 1.4142135624 3

This is quite a simple function with a single parameter x and a simple function result (the value of y).

Multiple parameters are separated by commas. The following function find finds the index of the first element in an array a with a value equal to x (there is a standard function for this: array.index).

function find(a, x)
  i=0;
  while i<len(a) and a[i]#x do
    i++
  end;
  return i
end

print find([9, 11, 13], 11)
→ 1
print find([9, 11, 13], 8)
→ 3

A function can be recursive, i.e. can call itself: the following function clone returns a full copy of its parameter t. It uses array.copy to copy all the elements, and .isarray to test whether t is an array.

function clone(t)
  if isarray(t) then
    c=array.copy(t);
    // recursively clone the elements
    for i=0 to len(t)-1 do c[i] = clone(t[i]) end;
    return c
  else
    return t
  end
end

If a function returns an array, the call can be followed by expressions in brackets accessing certain elements:

a=['one':1, 'two':2, 'three':3];
print keys(a)[2]
→ three

Function parameters are like local variables; they can optionally be declared to hold an instance of a given class. Likewise, the function can be declared to return an instance. See * () for examples and details.

Optional Parameters

Optional parameters are parameters with a default value: if the parameter is omitted, the default value is assumed. The expression to compute the default value can be any expression which is valid in the global context (i.e. it cannot use a preceding function parameter). It is evaluated when the function is called, not when the function is declared.

When calling a function, the number of actual parameters must not be less than the number of mandatory parameters in the declaration of the function, and not be greater than the total number of declared parameters.

The following rewrites function find by adding an optional parameter start indicating the position to start searching at. The default value of start is 0, so calling find with only two parameters produces exactly the same result as before:

function find(a, x, start=0)
  while start<len(a) and a[start]#x do
    start++
  end;
  return start
end

print find([9, 11, 13], 11)
→ 1
print find([9, 11, 13], 11, 2) // start=2
→ 3

Functions with optional parameters can have options for simplified syntax in interactive use (see section * ()). Options are simply single character names for optional parameters.

function grow(years,interest=2) /i:interest
  a=1;
  while years>0 do
    a+=a*interest/100; years--
  end;
  return a
end

grow(10,5)
→ 1.21899442
grow/i=5 10 // works only in interactive shells
→ 1.6288946268

Forward Declaration

Functions must be declared before they can be used. This means that if two functions call each other, at least one must be declared with forward and implemented later. In the following example, either f or g must be forward declared, since function f calls function g and vice versa:

function g(x, a=3.2) forward // g is made known

function f(x)
  if x<3 then
    return g(x*x) // g is called
  else
    return x+2
  end
end

function g(x, a=3.2) // here g is declared
  return f(x+a)
end

The default values of the optional parameters of the forward declared function are only used to mark optional parameters, their values are ignored. The default values are taken from the function implementation. The number of mandatory and optional parameters in forward declaration and implementation must match.

Function References

Function references allow to change the function called in an expression during the execution of a script: when a function reference is assigned to a variable or a parameter, the function can be called via the variable. The reference of a function is obtained by prefixing it with an ampersand character &:

f=&lower; // f now references the lower function
print f("Hello") // a call to lower
→ hello
f=&upper; // f now references the upper function
print f("Hello") // a call to upper
→ HELLO

Function references are often used to pass a function as a parameter to another function: the function integ approximates the integral of f from a to b:

function integ(f, a, b, n=100)
  s=(f(a)+f(b))/2; h=(b-a)/n;
  for i=1 to n-1 do
    s+=f(a+i*h)
  end;
  return s*h
end

function inv(x) return 1/x end
print integ(&inv, 1, 2)
→ 0.6931534305
print integ(&math.sin, 0, math.pi/2)
→ 0.9999794382
print integ(&math.sin, 0, math.pi/2, 10000)
→ 0.9999999979

FunctionDeclaration := function Identifier FunctionBody .
FunctionBody := '(' [ParameterList] ')' OptionalType
  ( forward | {FunctionOption} StatementList end ) .
ParameterList := (MandatoryParameter {',' MandatoryParameter} |
  OptionalParameter) {',' OptionalParameter} .
MandatoryParameter := VariableDeclaration .
OptionalParameter := VariableDeclaration '=' Expression .
FunctionOption := '/' OptionName ':' ParameterName .
OptionName := IdentifierChar | Digit .
ParameterName := Identifier .

ActualParameterList := Expression {',' Expression} .
FunctionCall :=
  ([ModulePrefix] Identifier '(' [ActualParameterList] ')' 
  { Selector } [ InstanceFunctionReference ] .
IndirectFunctionCall :=
  Designator '(' [ActualParameterList] ')' 
  { Selector } [ InstanceFunctionReference ] .


© 2004-2011 airbit AG, CH-8008 Zürich
Document AB-M-REF-887
mShell Home  > Documentation  > Manuals