4
votes

I am attempting to reference a procedure as a parameter of another procedure and am having trouble understanding the documentation.(http://docwiki.embarcadero.com/RADStudio/Sydney/en/Procedural_Types_(Delphi))

From what I understood I need to create a new type for the procedure..

type
  TCallback = procedure of object;

and declare the higher order procedure as procedure HigherOrder(pProc: TCallback);

I receive the compilation error " E2010 Incompatible types: 'TCallBack' and 'procedure, untyped pointer or untyped parameter' " when attempting to call the function(when the button is clicked)

type
  TCallBack = procedure of object;
  TfrmMain = class(TForm)
    btnAct: TButton;
    procedure btnActClick(Sender: TObject);
  private
    procedure HigherOrder(pProc: TCallback);
    procedure Callback();
    { Private declarations }
  public
    { Public declarations }
  end;

var
  frmMain: TfrmMain;

implementation

{$R *.dfm}

{ TfrmMain }

procedure TfrmMain.btnActClick(Sender: TObject);
begin
  HigherOrder(Callback()); <--Error occurs here
end;

procedure TfrmMain.Callback;
begin
  //Do some stuff
end;

procedure TfrmMain.HigherOrder(pProc: TCallback);
begin
  //Do some other stuff
  pProc();
end;

end.

Any help is greatly appreciated. I am quite new to programming in delphi.

1

1 Answers

11
votes

The problem is that you are calling Callback() first and then trying to pass its return value (which, it doesn't have one) to HigherOrder(), but that is not what HigherOrder() is expecting, which is why you are getting the error. In other words, your code is roughly equivalent to this:

procedure TfrmMain.btnActClick(Sender: TObject);
begin
  //HigherOrder(Callback());
  var res := Callback();
  HigherOrder(res);
end;

Except that the type of res is undefined since Callback() is a procedure and not a function.

When calling HigherOrder(), you need to remove the trailing () parenthesis from Callback() in order to pass Callback itself (well, its memory address, anyway) as the value of the pProc parameter, eg:

procedure TfrmMain.btnActClick(Sender: TObject);
begin
  HigherOrder(Callback);
end;

Yes, you can also drop the parenthesis when calling a procedure without passing any parameters to it. But, in this case, the compiler is smart enough to know that the parenthesis-omitting Callback identifier is being assigned to a closure type and so will pass it as-is and not call it.