Tutorial - Routine Type

Routine Type

It is possible to create a type that contains a routine ( Function or Shape ). A variable of this type can contain any routine with the correct signature ( parameter types and return type ).

This concept is easier to explain with a simple example.

Type SimpleFunct = Number(Number n);	[= 1 =]
Program()
	SimpleFunct trigfn = Sin;	[= 2 =]
    Begin
	Output trigfn(30);		[= 3 =] 
    End;

The type declaration ( statement 1 ), defines a type "SimpleFunct" to be a function that takes a single numeric parameter and return a numeric value.

The variable declaration ( statement 2 ) creates a variable of this type, so the variable 'trigfn' can take any function that matches the signature. In this case we are initialising it to the built in function Sin.

In the Output code ( statement 3 ) you are calling the function that is stored in 'trigfn' - in this case Sin.

Advanced Example

The following example uses the planet symbol routines written in previous tutorials. This example illustrates the versatility of the mechanism. You can use Shape as well as functions. And you can use routine types as fields in a structure. The 'planet' field is a Shape routine. So following that field with a parameters list will invoke the particular Shape held within the field. Remember even if the parameter list is empty you still need the parentheses.

Type PlanetShape = Shape(Number size);
Type PlanetRec = { Point posn, PlanetShape planet };
Type PlanetList = PlanetRec[];

Const PlanetList DemoList = [  {{50, 100}, MercurySymbol}, {{100, 100}, VenusSymbol},
					{{150, 100}, EarthSymbol}, {{200, 100}, MarsSymbol}  ];
Program( )
    Begin
	Over DemoList As item Do
		item.planet(20) => item.posn;
	EndOver;
    End;
type_routfn_1.grs Output of type_routfn_1.grs type_routfn_1.png

Parameter Attributes

Each parameter for a routine can have a Const or Ref attribute. There are rules governing how these are checked.

The Ref Attribute

If the Ref attribute is specified for a parameter in the type then the Ref attribute of the corresponding parameter in the routine being assigned to the variable of that function type must have a matching attribute.

The Const Attribute

If a parameter in a function type has the Const attribute the only routines with the corresponding parameter also set to constant may be assigned. If the type does not have the Const attribute then the corresponding parameter can be either Const or not.

Parameter Names

When calling a function using parameter names via a variable the compiler expect the names used in the type definition not the variable name used in the actual function definition.

Type TMyFunct = Number(Number parm1);
Program( )
	TMyFunct fn;
	Number res;
    Begin
	fn := TestFunct;
	res := fn(parm1 -> 42);
    End;

Function Number TestFunct(Number a)  Begin Return a + 1; End;

Parameter Defaults

When calling a routine via a routine variable the default parameters of the original routine are not accessible. You can however define default parameters in the type definition.

So the following function call will return 101 rather than 43.

Type TMyFunct = Number(Number parm1 = 100);

Program( )
	TMyFunct fn;
	Number res;
    Begin
	fn := TestFunct;
	res := fn();
    End;

Function Number TestFunct(Number a = 42)
    Begin
	Return a + 1;
    End;