the call through variables mechanism is rather confusing to say the least.
Consider the following code (modified from BrunoK's):
{$MODE OBJFPC}
program Project1;
procedure ProcCalledByPointer;
begin
writeln('proc CalledByPointer was executed');
end;
function FuncCalledByPointer : boolean;
begin
result := TRUE;
writeln('func - 1 - CalledByPointer was executed');
end;
function FuncCalledByPointer(p : integer) : pointer;
begin
result := nil;
inc(p);
writeln('func - 2 - CalledByPointer was executed');
end;
var
vProc : procedure;
vFunc : function() : boolean;
vFunc2 : function(p : integer) : pointer;
begin
if Assigned(vProc) then
WriteLn('Assigned(vProc)');
if vProc<>nil then
WriteLn('vProc<>nil');
vProc := @ProcCalledByPointer;
if Assigned(vProc) then
WriteLn('after vProc := @... Assigned(vProc)');
if vProc <> nil then
WriteLn('after vProc := @... vProc<>nil');
vproc;
{ ------------------------------------------------------------------------- }
{ now with a function }
if Assigned(vFunc) then
WriteLn('Assigned(vFunc)');
if vFunc<>nil then
WriteLn('vFunc<>nil');
vFunc := @FuncCalledByPointer;
if Assigned(vFunc) then
WriteLn('after vFunc := @... Assigned(vFunc)');
{ parentheses make a difference, i.e, vFunc <> vFunc() }
if vFunc <> nil then
WriteLn('after vFunc := @... vFunc<>nil');
vFunc; { parentheses DON'T make a difference here, i.e, vFunc = vFunc() }
{ ------------------------------------------------------------------------- }
{ now with a function that takes parameters }
if Assigned(vFunc2) then
WriteLn('Assigned(vFunc2)');
if vFunc2<>nil then
WriteLn('vFunc2<>nil');
vFunc2 := @FuncCalledByPointer;
if Assigned(vFunc2) then
WriteLn('after vFunc2 := @... Assigned(vFunc2)');
if vFunc2 <> nil then
WriteLn('after vFunc2 := @... vFunc2<>nil');
if vFunc2(1) <> nil then
WriteLn('after vFunc2 := @... vFunc2<>nil');
vFunc2(1);
writeln;
writeln('press ENTER/RETURN to end this program');
ReadLn;
end.
The difference between the highlighted lines is subtle enough that it would be reasonable for a programmer to not know why in one case the vFunc target is not called yet it is called in the other case that looks (but isn't) identical.
As MarkMLI pointed out, Pascal's not requiring the parentheses to indicate a call is being made is a flaw in the language. One that can bite even an experienced programmer.
Suggestion: _always_ put the parentheses, that way when the parentheses are missing, whoever is reading the code may suspect there is something different going on there.
It would be very nice if FPC had some modeswitch that made the parentheses required for a function or procedure to be called, i.e, no parentheses = it's a variable reference, not a call.
ETA:
corrected a typo.