Seed7 - The extensible programming language
Seed7 FAQ Manual Screenshots Examples Libraries Algorithms Download Links
Manual Introduction Tutorial Declarations Statements Types Parameters Objects File System Syntax Tokens Expressions OS access Actions Foreign funcs Errors
Parameters val ref in in var inout Symbol attr
Manual
Parameters
 previous   up   next 

6. PARAMETERS

The following sub-chapters introduce the parameter types of Seed7.

6.1 'val' parameter

Value parameters are marked with the keyword 'val'. A value parameter copies the value of the actual parameter. Value parameters are used, when copying is cheap or when copying is necessary for the correct behavior. The function below appends a comma and a string to the variable 'globalStri':

const proc: appendStri (val string: stri) is func
  begin
    globalStri &:= ",";
    globalStri &:= stri;
  end func;

After doing

globalStri &:= "a";
appendStri(globalStri);

the variable globalStri contains the value "a,a". If the function header would be

const proc: appendStri (in string: stri) is func

the variable globalStri would contain the value "a,a,". This difference is because of the following reasons:

For arrays 'in' parameters are equal to 'ref' parameters. When appendStri is called with globalStri as parameter an unwanted side effect takes place: Every change of globalStri changes also the 'ref' parameter stri. Changes to the 'ref' parameter would also change the global variable. Such unwanted side effects can also take place between parameters (when at least one parameter is an 'inout' parameter).

In most cases such unwanted side effects are impossible or can be avoided easily. An 'in' parameter should be preferred over an 'val' parameter, when possible.

Semantics:
When calling a function a formal 'val' parameter gets its value from the corresponding actual parameter. This is done with a create procedure ( ::= ). In the function it is only possible to read a formal 'val' parameter. Changing a formal 'val' parameter is not possible. When a function is left a 'destr' procedure is called for every 'val' parameter. Formal 'val' parameters have the access right 'const'.
Syntax:
val_parameter ::=
'val' type_expression ':' identifier_declaration |
'val' type_expression 'param' .

Declaration:

$ syntax expr: .val.().param       is -> 40;
$ syntax expr: .val.(). : .(expr)  is -> 40;

const func f_param: val (ref type param) param               is action "DCL_VAL1";
const func f_param: val (ref type param) : (ref expr param)  is action "DCL_VAL2";

6.2 'ref' parameter

Reference parameters are marked with the keyword 'ref'. A reference parameter refers to the value of the actual parameter. Reference parameters are used, when copying is expensive and referring to the value does not change the correct behavior. The function below defines the primitive action for the semicolon operator:

const proc: (ref void: statement1) ; (ref void: statement2) is noop;

In this definition and other definitions of primitive actions 'ref' parameters are used. For normal functions usually 'in' parameters are used instead of 'ref' parameters:

const func integer: total_length (in array string: arr) is func
  result
    var integer: lengthSum is 0;
  local
    var integer: index is 0;
  begin
    for index range 1 to length(arr) do
      lengthSum +:= length(arr[index]);
    end for;
  end func;

Above function could also be defined with the following function head:

const func integer: total_length (ref array string: arr) is func

Since for array types (and also for struct types) 'in' parameters are defined to act as 'ref' parameters both definitions are equal. An 'in' parameter should be preferred over an 'ref' parameter, when possible.

Semantics:
When calling a function a formal 'ref' parameter is set to refer to the corresponding actual parameter. In the function it is only possible to read a formal 'ref' parameter. Changing a formal 'ref' parameter is not possible. Formal 'ref' parameters have the access right 'const'.
Syntax:
ref_parameter ::=
'ref' type_expression ':' identifier_declaration |
'ref' type_expression 'param' .

Declaration:

$ syntax expr: .ref.().param       is -> 40;
$ syntax expr: .ref.(). : .(expr)  is -> 40;

const func f_param: ref (ref type param) param               is action "DCL_REF1";
const func f_param: ref (ref type param) : (ref expr param)  is action "DCL_REF2";

6.3 'in' parameter

Input parameters are marked with the keyword 'in'. Depending on the type an input parameter is either a value or a reference parameter. The function below checks if a given number is a prime number:

const func boolean: is_prime (in integer: number) is func
  result
    var boolean: prime is FALSE;
  local
    var integer: count is 2;
  begin
    if number = 2 then
      prime := TRUE;
    elsif number >= 3 then
      while number rem count <> 0 and count * count <= number do
        incr(count);
      end while;
      prime := number rem count <> 0;
    end if;
  end func;

The following function defines the ex (outer) product:

const func array array integer:
    (in array integer: a) ex (in array integer: b) is func
  result
    var array array integer: product is 0 times 0 times 0;
  local
    var integer: index1 is 1;
  begin
    product := length(a) times length(b) times 0;
    for index1 range 1 to length(a) do
      for index2 range 1 to length(b) do
        product[index1][index2] := a[index1] * b[index2];
      end for;
    end for;
  end func;

Although both examples use 'in' parameters the parameter in the first example is actually a 'val' parameter while the parameters in the second example are actually 'ref' parameters. When a new type is created with the 'newtype' function it is necessary to specify the meaning of the 'in' parameter. This is done with a call of the IN_PARAM_IS_VALUE or the IN_PARAM_IS_REFERENCE function with the new generated type as parameter. If a new type is created with the 'subtype' function this specification is optional since the base type has already a specification of the 'in' parameter.

Semantics:
Depending on the type an 'in' parameter is equivalent to an 'val' (call by value) parameter or to an 'ref' (call by reference) parameter. Formal 'in' parameters have the access right 'const'.
Syntax:
in_parameter ::=
'in' type_expression ':' identifier_declaration .

Declaration:

$ syntax expr: .in.().param       is -> 40;
$ syntax expr: .in.(). : .(expr)  is -> 40;

const func f_param: in (ref type param) param                is action "DCL_REF1";

const proc: IN_PARAM_IS_VALUE (ref type: aType) is func
  begin
    const func f_param: in (attr aType) : (ref expr param)   is action "DCL_VAL2";
  end func;

const proc: IN_PARAM_IS_REFERENCE (ref type: aType) is func
  begin
    const func f_param: in (attr aType) : (ref expr param)   is action "DCL_REF2";
  end func;

6.4 'in var' parameter

This function computes the greatest common divisor:

const func integer: gcd (in var integer: a, in var integer: b) is func
  result
    var integer: gcd is 0;
  local
    var integer: help is 0;
  begin
    while a <> 0 do
      help := b rem a;
      b := a;
      a := help;
    end while;
    gcd := b;
  end func;

Semantics:
When calling a function a formal in var parameter gets its value from the corresponding actual parameter. This is done with a create procedure ( ::= ). In the function it is possible to read and change a formal in var parameter. Changing a formal in var parameter has no effect on the actual parameter. When a function is left a 'destr' procedure is called for every in var parameter. Formal in var parameters have the access right var.
Syntax:
in_var_parameter ::=
'in var' type-expression ':' identifier_declaration .

Declaration:

$ syntax expr: .in.var.().param       is -> 40;
$ syntax expr: .in.var.(). : .(expr)  is -> 40;

const func f_param: in var (ref type param) param               is action "DCL_IN1VAR";
const func f_param: in var (ref type param) : (ref expr param)  is action "DCL_IN2VAR";

6.5 'inout' parameter

This procedure doubles the given parameter 'number':

const proc: double (inout integer: number) is func
  begin
    number := 2 * number;
  end func;

Semantics:
When calling a function a formal 'inout' parameter is set to refer to the corresponding actual parameter. In the function it is possible to read and change a formal 'inout' parameter. Changing a formal 'inout' parameter changes the actual parameter as well. Formal 'inout' parameters have the access right 'var'.
Syntax:
inout_parameter ::=
'inout' type_expression ':' identifier_declaration .

Declaration:

$ syntax expr: .inout.().param       is -> 40;
$ syntax expr: .inout.(). : .(expr)  is -> 40;

const func f_param: inout (ref type param) param               is action "DCL_INOUT1";
const func f_param: inout (ref type param) : (ref expr param)  is action "DCL_INOUT2";

6.6 Symbol parameter

Some functions need symbols at fixed places in the parameter list. The following IF-statement requests the keywords 'THEN', 'END' and 'IF' at specific places:

IF condition THEN
  statement
END IF;

After defining the syntax of this IF-statement with

$ syntax expr: .IF.().THEN.().END.IF  is -> 25;

the semantic can be defined with:

const proc: IF (in boolean: condition) THEN
              (in proc: statement)
            END IF is func

              begin
                case condition of
                  when {TRUE}: statement;
                end case;
              end func;

The symbol parameters are just written outside the parentheses. A call of this statement could be:

IF value < maximum THEN
  write(value)
END IF;

Semantics:
Symbol parameters must be defined in a syntax definition and in a corresponding semantic definition. In the semantic definition symbol parameters are written outside of the parentheses. In the actual parameter list the corresponding symbol of the formal parameter list must be written.
Syntax:
symbol_parameter ::=
name_identifier | special_identifier .

6.7 'attr' parameter

This declaration associates a name to the type 'char':

const string: name (attr char) is "char";

This 'name' can be used as follows:

writeln(name(char));

It is possible to overload such declarations:

const string: name (attr boolean)  is "boolean";
const string: name (attr float)    is "float";

An 'attr' parameter can be used in a function also:

const func char: (attr char) parse (in string: stri) is
  return stri[1];

Semantics:
The actual parameter which corresponds to an 'attr' parameter must be the type mentioned in the declaration of the 'attr' parameter. An 'attr' parameter does not declare a formal parameter variable which could be used inside a function.
Syntax:
attr_parameter ::=
'attr' type_expression .


 previous   up   next