In an assignment, how can I distinguish between assigning the return value of a function that takes no parameters (and therefore the call may have no parens), and assigning the function reference itself. Is it only by looking at the type of the receiving variable?
Here is a code fragment for illustration (Delphi noob here):
type
TIntFun = function():integer;
var
IntFun : TIntFun;
I : integer;
function AnIntFun(): integer;
begin
result := 3;
end;
begin
I := AnIntFun; // argumentless call, returning 3
IntFun := AnIntFun; // function assignment?
end
Is it only by looking at the type of the receiving variable?
Yes.
This is, in my view, a strong argument against allowing the function call syntax to omit parens. If that language feature did not exist, then you would have to write:
I := AnIntFun();
IntFun := AnIntFun;
If you were forced to write it this way then the compiler would regard
I := AnIntFun;
as a syntax error. The expression AnIntFun
would always be of procedural type and the compiler (and the reader) would not need to rely on context to determine the type of the expression.
Relying on context to determine the type of the expression is very undesirable. Consider for instance function overloading:
procedure foo(fun: TIntFun); overload;
procedure foo(val: Integer); overload;
When you write:
foo(AnIntFun);
which overload do you think is chosen? If the language required parens on every function call then AnIntFun
is always of procedural type, and the first overload would be chosen without ambiguity.
Your code will work as expected.
But to be explicit, you can write AnIntFun()
if you want to execute the function and @AnIntFun
if you mean the function itself.
program Project1;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils;
type
TIntFcn = function: Integer;
procedure Test(Val: Integer); overload;
begin
Writeln('Value: ' + Val.ToString);
end;
procedure Test(Fcn: TIntFcn); overload;
begin
Writeln('Function. Returned value: ' + Fcn.ToString);
end;
function TestFcn: Integer;
begin
Result := 3;
end;
begin
Test(TestFcn()); // value (obvious)
Test(@TestFcn); // fcn (obvious)
Test(TestFcn); // value
Readln;
end.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With