Free Pascal functions with multiple return-values.
As a difference with programming languages as for example C, Free Pascal functions allow one single return value only. This is not a big deal, as Pascal includes a second subroutine type, the procedures, and you can use out arguments to return as many values as you want. If, for example, you want to write a subroutine that sorts an array of integers, with the original array as input, and the sorted array as output, you can create the corresponding procedure as in the following simple program:
		    program bubble_sort;
            type
                TArray = array of Integer;
            var
                I: Integer;
                Arr1, Arr2: TArray;
		    // Bubble sort procedure
            procedure Sort(var A1: TArray; out A2: TArray);
            var
                Temp, I, J: Integer;
            begin
                SetLength(A2, Length(A1)); A2 := A1;
                for I := 0 to Length(A2) - 2 do begin
                    for J := I + 1 to Length(A2) - 1 do begin
                        if A2[I] > A2[J] then begin
                            Temp := A2[I]; A2[I] := A2[J]; A2[J] := Temp;
                        end;
                    end;
                end;
            end;
		    // Main program
            begin
                SetLength(Arr1, 10);
                Arr1 := [2, 4, 8, 1, 9, 3, 6, 7, 5, 0];
                Sort(Arr1, Arr2);
                for I := 0 to Length(Arr2) - 1 do
                    Write(Arr2[I], ' ');
                Writeln;
                Write('ENTER to terminate '); Readln;
            end.         
      
Note: The usage of a custom data type (TArray) is mandatory, because: first, trying to use SetLength with a variable of type array of Integer would result in a "Type mismatch" error, and second with A1 and A2 being of type array of Integer, the statement A2 := A1 would result in an "Assignments to formal parameters and open arrays are not possible" error.
However, the functions in Free Pascal are well limited to a single return-value, but not to a scalar data type of the return-value. This means that functions may return structured values, such as arrays and records. And, there is no problem to declare our sort routine as a function, as shown in the program below:
          program bubble_sort2;
          type
              TArray = array of Integer;
          var
              I: Integer;
              Arr1, Arr2: TArray;
	      // Bubble sort function
          function Sort(var A1: TArray): TArray;
          var
              Temp, I, J: Integer;
	          A2: TArray;
          begin
              SetLength(A2, Length(A1)); A2 := A1;
              for I := 0 to Length(A2) - 2 do begin
                  for J := I + 1 to Length(A2) - 1 do begin
                      if A2[I] > A2[J] then begin
                          Temp := A2[I]; A2[I] := A2[J]; A2[J] := Temp;
                      end;
                  end;
              end;
              Result := A2;
          end;
	      // Main program
          begin
              SetLength(Arr1, 10);
              Arr1 := [2, 4, 8, 1, 9, 3, 6, 7, 5, 0];
              Arr2 := Sort(Arr1);
              for I := 0 to Length(Arr2) - 1 do
                  Write(Arr2[I], ' ');
              Writeln;
              Write('ENTER to terminate '); Readln;
          end.         
      
In fact, our example is just a special form of a single value return. But, an array return-value can also be used if the function "really" calculates two or more different values. Example: Consider a serial AC RLC circuit with known frequency (F), resistance (R), inductance (L) and capacitance (C), and lets write a function that calculates the total impedance of the circuit. As this impedance actually is a vector, this has to be a two return-values function, the first being the vector's amplitude and the second its angle, in other words, the impedance Z and the phase angle φ. As a Free Pascal function may only return one value, we can either use a procedure, or write 2 functions, or return a two-elements array, where the first element is the impedance, and the second is the phase angle. Here is a simple program that shows how to implement this:
	  
	      program rlc;
          type
              TArray = array[0..1] of Real;
          var
              F, R, L, C, Z, Phi: Real;
              Impedance: TArray;
	      // Serial RLC circuit function
          function SerialImpedance(F, R, L, C: Real): TArray;
          var
              XL, XC: Real;
              SerImp: TArray;
          begin
              XL := 2 * 3.14 * F * L;
              XC := 1 / (2 * 3.14 * F * C);
	          // Impedance
              SerImp[0] := Sqrt(Sqr(R) + Sqr(XL - XC));
	          // Phase angle
              SerImp[1] := 360 * Arctan((XL - XC) / R) / (2 * Pi);
              Result := SerImp;
          end;
          // Main program
          begin
              F := 80; R := 203; L := 0.8; C := 390E-6;
              Impedance := SerialImpedance(F, R, L, C);
              Z := Impedance[0]; Phi := Impedance[1];
              Writeln('Impedance Z     = ', Z:7:2);
              Writeln('Phase angle phi = ', Phi:7:2);
              Writeln;
              Write('ENTER to terminate '); Readln;
          end.        
	  
Note: The array returned by a function must have been defined as a custom data type (TArray in our case).
Lets extend the SerialImpedance function, also returning a textual indication concerning the phase shift between the current and the voltage. A first possibility would be to use a third real value functioning as a code, ex: 0 = in phase, -1 = current leads, 1 = current lags. However, it is possible to return real values and strings in the same array. All we have to do is to use an array of Variant (for details, cf. my tutorial Special data types: Variants, variant records, and variant arrays). Here is the code:
	  
	      program rlc2;
          uses
              Variants;
          type
              TArray = array[0..2] of Variant;
          var
              F, R, L, C, Z, Phi: Real;
              PhaseShift: string;
              Impedance: TArray;
	      // Serial RLC circuit function
          function SerialImpedance(F, R, L, C: Real): TArray;
          var
              XL, XC, P: Real;
              SerImp: TArray;
          begin
              XL := 2 * 3.14 * F * L;
              XC := 1 / (2 * 3.14 * F * C);
	          // Impedance
              SerImp[0] := Sqrt(Sqr(R) + Sqr(XL - XC));
	          // Phase angle
              SerImp[1] := 360 * Arctan((XL - XC) / R) / (2 * Pi);
	          // Phase shift
              if SerImp[1] = 0 then
                  SerImp[2] := 'Current and voltage are in phase.'
              else if SerImp[1] < 0 then
                  SerImp[2] := 'The current leads the voltage.'
              else
                  SerImp[2] := 'The current lags the voltage.';
              Result := SerImp;
          end;
	      // Main program
          begin
              F := 90; R := 710; L := 0.1; C := 228E-6;
              Impedance := SerialImpedance(F, R, L, C);
              Z := Impedance[0]; Phi := Impedance[1];
              PhaseShift := Impedance[2];
              Writeln('Impedance Z     = ', Z:7:2);
              Writeln('Phase angle phi = ', Phi:7:2);
              Writeln(PhaseShift);
              Writeln;
              Write('ENTER to terminate '); Readln;
          end.        
	  
	  
A better way to implement the function consists in using a record as return-value. Not only that Variant are said to be slow, but also, this gives us the possibility to label the different elements of the return structure (instead of using indexes). Here is the new code:
	  
          program rlc3;
          type
              TImpedance = record
                  Z, Phi: Real;
                  PhaseShift: string;
              end;
          var
              F, R, L, C: Real;
              Impedance: TImpedance;
          // Serial RLC circuit function
          function SerialImpedance(F, R, L, C: Real): TImpedance;
          var
              XL, XC: Real;
              SerImp: TImpedance;
          begin
              XL := 2 * 3.14 * F * L;
              XC := 1 / (2 * 3.14 * F * C);
              with SerImp do begin
                  Z   := Sqrt(Sqr(R) + Sqr(XL - XC));
                  Phi := 360 * Arctan((XL - XC) / R) / (2 * Pi);
                  if Phi = 0 then
                      PhaseShift := 'Current and voltage are in phase.'
                  else if Phi < 0 then
                      PhaseShift := 'The current leads the voltage.'
                  else
                      PhaseShift := 'The current lags the voltage.';
              end;
              Result := SerImp;
          end;
          // Main program
          begin
              F := 90; R := 710; L := 0.1; C := 228E-6;
              Impedance := SerialImpedance(F, R, L, C);
              with Impedance do begin
                  Writeln('Impedance Z     = ', Z:7:2);
                  Writeln('Phase angle phi = ', Phi:7:2);
                  Writeln(PhaseShift);
              end;
              Writeln;
              Write('ENTER to terminate '); Readln;
          end.	  
      
If you find this text helpful, please, support me and this website by signing my guestbook.