在分配中,如何区分分配不带参数的函数的返回值(因此调用可能没有括号)和分配函数引用本身。是否仅通过查看接收变量的类型?
这是用于说明的代码片段(此处是Delphi noob):
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
Run Code Online (Sandbox Code Playgroud)
是否仅通过查看接收变量的类型?
是。
在我看来,这是反对允许函数调用语法省略parens的强烈理由。如果该语言功能不存在,那么您将必须编写:
I := AnIntFun();
IntFun := AnIntFun;
Run Code Online (Sandbox Code Playgroud)
如果您被迫以这种方式编写,那么编译器会认为
I := AnIntFun;
Run Code Online (Sandbox Code Playgroud)
作为语法错误。表达式AnIntFun将始终是过程类型的,并且编译器(和读者)将不需要依赖上下文来确定表达式的类型。
依靠上下文确定表达式的类型是非常不可取的。考虑实例函数重载:
procedure foo(fun: TIntFun); overload;
procedure foo(val: Integer); overload;
Run Code Online (Sandbox Code Playgroud)
当你写:
foo(AnIntFun);
Run Code Online (Sandbox Code Playgroud)
您认为选择了哪种过载?如果在每次函数调用时都要求使用语言,则该语言AnIntFun始终是过程类型的,并且选择第一个重载时不会产生歧义。
您的代码将按预期工作。
但是为了明确起见,您可以编写AnIntFun()是否要执行该函数以及@AnIntFun是否表示该函数本身。
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.
Run Code Online (Sandbox Code Playgroud)