Difference between revisions of "How to use procedural variables"

From Free Pascal wiki
Jump to navigationJump to search
(FPC 2.4.x requires different Type for procedures)
m (Actually add page template :-)
 
(9 intermediate revisions by 5 users not shown)
Line 1: Line 1:
Copy the text below and it will demonstrate the use of procedural variables, this is a fully working program. You don't even need to understand how it works the syntax is pretty simple.
+
{{How_to_use_procedural_variables}}
  
----
+
Copy the text below and it will demonstrate the use of procedural variables, this is a fully working program. You don't even need to understand how it works. The syntax is pretty simple.
<delphi>program Test;
+
 
 +
<syntaxhighlight lang=pascal>
 +
program Test;
  
 
{$mode objfpc}{$H+}
 
{$mode objfpc}{$H+}
Line 44: Line 46:
 
begin
 
begin
 
   // the "@" symbol turns the variable into a pointer.
 
   // the "@" symbol turns the variable into a pointer.
   // This must be done in order pass a function as a  
+
   // This must be done in order pass a function as a
   // paramater.  This also demonstrates that pascal
+
   // parameter.  This also demonstrates that pascal
 
   // keeps track of the pointer type so the overloading works!
 
   // keeps track of the pointer type so the overloading works!
  
Line 60: Line 62:
 
   WriteLn(TFuncNoArgsString(List[0]));
 
   WriteLn(TFuncNoArgsString(List[0]));
 
   ReadLn;
 
   ReadLn;
end.</delphi>
+
end.</syntaxhighlight>
----
+
 
'''Note for FPC 2.4.x:'''
+
With <code>{$modeswitch classicprocvars+}</code> the [[@|<code>@</code>-address-operator]] is not necessary to refer to methods.
Defining a type for a procedure now requires it to be of type "procedure of object" instead of just "procedure", otherwise the following compiler error will occur when assigning a procedure to your variable:
+
Also, if you are using the <code>@</code>-address-operator usage of <code>{$typedaddress on}</code> is advised in order to prevent programming mistakes.
Error: Incompatible types: got "<procedure variable type of procedure of object;Register>" expected "<procedure variable type of procedure;Register>"
 

Latest revision as of 07:30, 17 February 2020

English (en)

Copy the text below and it will demonstrate the use of procedural variables, this is a fully working program. You don't even need to understand how it works. The syntax is pretty simple.

program Test;

{$mode objfpc}{$H+}
uses
  {$IFDEF UNIX}{$IFDEF UseCThreads}
  cthreads,
  {$ENDIF}{$ENDIF}
  Classes;

// Make the Types the type corresponds to a function signature
type
  TFuncNoArgsString = function(): String;
  TFuncOneArgsString = function(x: string): string;

// Example functions
function Hello: String;
begin
  Result := 'Hello There';
end;

function Woah(G: String): String;
begin
  Result := 'Woah ' + G;
end;

// Overloaded function takes the two types of function
// pointers created above
procedure Take(f: TFuncNoArgsString); overload;
begin
  WriteLn(f());
end;

procedure Take(f: TFuncOneArgsString); overload;
begin
  WriteLn(f('there!!!'));
end;

var
  ptr: Pointer;
  List: TList;
begin
  // the "@" symbol turns the variable into a pointer.
  // This must be done in order pass a function as a
  // parameter.  This also demonstrates that pascal
  // keeps track of the pointer type so the overloading works!

  Take(@Hello);
  Take(@Woah);

  // Now put a function in an untyped pointer
  ptr := @Hello;
  // Type the pointer and call it all at the same time
  WriteLn(TFuncNoArgsString(ptr));
  // A TList Example
  List := TList.Create;
  List.Add(@Hello);
  WriteLn(TFuncNoArgsString(List[0]));
  ReadLn;
end.

With {$modeswitch classicprocvars+} the @-address-operator is not necessary to refer to methods. Also, if you are using the @-address-operator usage of {$typedaddress on} is advised in order to prevent programming mistakes.