Difference between revisions of "How to use procedural variables"

From Lazarus wiki
m (Actually add page template :-)
 
(16 intermediate revisions by 8 users not shown)
Line 1: Line 1:
Copy the text below and it will demonstrate the use of function pointers, this is a full 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.
<pre>
+
 
program test;
+
<syntaxhighlight lang=pascal>
 +
program Test;
  
 
{$mode objfpc}{$H+}
 
{$mode objfpc}{$H+}
Line 10: Line 11:
 
   cthreads,
 
   cthreads,
 
   {$ENDIF}{$ENDIF}
 
   {$ENDIF}{$ENDIF}
   Classes
+
   Classes;
  { add your units here };
+
 
//Make the Types the type corresponds to a function signature
+
// Make the Types the type corresponds to a function signature
 
type
 
type
    TFuncNoArgs_String = function():String;
+
  TFuncNoArgsString = function(): String;
    TFuncOneArgs_String = function(x:string):string;
+
  TFuncOneArgsString = function(x: string): string;
  
//example functions
+
// Example functions
function Hello():String;
+
function Hello: String;
 
begin
 
begin
    result:='Hello There';
+
  Result := 'Hello There';
 
end;
 
end;
function Woah(G:String):String;
+
 
 +
function Woah(G: String): String;
 
begin
 
begin
    result:='Woah ' + G;
+
  Result := 'Woah ' + G;
 
end;
 
end;
  
//overloaded function takes the two types of function
+
// Overloaded function takes the two types of function
//pointers created above
+
// pointers created above
procedure Take(f:TFuncNoArgs_String);overload;
+
procedure Take(f: TFuncNoArgsString); overload;
 
begin
 
begin
    writeln(f());
+
  WriteLn(f());
 
end;
 
end;
  
procedure Take(f:TFuncOneArgs_String);overload;
+
procedure Take(f: TFuncOneArgsString); overload;
 
begin
 
begin
    writeln(f('there!!!'));
+
  WriteLn(f('there!!!'));
 
end;
 
end;
  
 +
var
 +
  ptr: Pointer;
 +
  List: TList;
 
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!
 +
 
 +
  Take(@Hello);
 +
  Take(@Woah);
  
Take(@Hello);
+
  // Now put a function in an untyped pointer
Take(@Woah);
+
  ptr := @Hello;
readln;
+
  // Type the pointer and call it all at the same time
end.  
+
  WriteLn(TFuncNoArgsString(ptr));
</pre>
+
  // A TList Example
 +
  List := TList.Create;
 +
  List.Add(@Hello);
 +
  WriteLn(TFuncNoArgsString(List[0]));
 +
  ReadLn;
 +
end.</syntaxhighlight>
  
----
+
With <code>{$modeswitch classicprocvars+}</code> the [[@|<code>@</code>-address-operator]] is not necessary to refer to methods.
 +
Also, if you are using the <code>@</code>-address-operator usage of <code>{$typedaddress on}</code> is advised in order to prevent programming mistakes.

Latest revision as of 08: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.