Delphi's function call syntax is a little different from most other languages. In most languages, in order to call a function you must use parens ()
after the function name, commonly referred to as the function call operator. If the function is simply named, and no parens supplied, that expression evaluates to the function without invoking a call.
So, with the C++ language as our example,
i = foo();
calls the function and stores the return value in i
.
On the other hand,
fn = foo;
stores the address of the function in the function pointer variable fn
.
Delphi varies from this, for a parameterless function, by allowing you to omit the parens, and yet still call the function. So in Delphi, the first line of code above could be written
i := foo;
and this would call the function.
Where it gets slightly tricky is if the function return type is a procedural type, a method, or an anonymous method, as you have found out.
In your scenario,
v1 := GetHandler;
is ambiguous in the eyes of the compiler. Because v1
is a variable whose type is an anonymous method, the compiler will never generate a call when parens are omitted. If it did generate a call then you would not be able to make the simple assignment of a function to a procedural type variable.
So the compiler switches to the behaviour that you find in languages like C++. You must supply parens if you wish for the function to be called. To make your code compile and work, write
v1 := GetHandler();
The documentation covers the issue in some detail. The key excerpt is this:
In assignment statements, the type of the variable on the left determines the interpretation of procedure or method pointers on the right.
Now, casting judgement, I find the idea that the context of an expression can determine its interpretation to be rather unsettling. This all stems from allowing function calls to be made when parens are omitted. I would rather have to use parens always and so avoid the ambiguities discussed above. In particular this would allow expression meaning to be independent of context.
To see what I mean, we return to my original example. Let us now be more specific about the types involved:
type
TIntFunc = function: Integer;
function foo: Integer;
begin
Result := 42;
end;
var
i: Integer;
fn: TIntFunc;
At this point we can write:
i := foo; // i is an integer, so the function is called
fn := foo; // fn is a procedural type variable, so the function is not called
I personally find this state of affairs not at all satisfactory.