Recent

Author Topic: Procedure with parameters as a parameter of procedure  (Read 603 times)

TomTom

  • Full Member
  • ***
  • Posts: 170
Procedure with parameters as a parameter of procedure
« on: November 28, 2022, 07:03:20 pm »
I have this procedure that I want to use as a argument of another procedure
Code: Pascal  [Select][+][-]
  1. procedure TForm1.UpdateGameDetails(aGamesList: TStringList;
  2.   aGameIndex: integer; aGameDetail: TGameDetails; aValue:string);
  3. var
  4.   new_value: string;
  5.   i: Integer;
  6.   temp_table: TStringDynArray;
  7. begin
  8.   new_value:='';
  9.   temp_table :=SplitString(aGamesList[aGameIndex],';');
  10.   temp_table[Ord(aGameDetail)] := aValue;
  11.   for i:= low(temp_table) to Length(temp_table) do begin
  12.     new_value := new_value+temp_table[i]+';';
  13.   end;
  14.  aGamesList[aGameIndex]:=new_value;
  15.  aGamesList.SaveToFile('games');
  16. end;
  17.  
  18.  

In Lable1.OnClick event:
Code: Pascal  [Select][+][-]
  1. procedure TForm1.Label1Click(Sender: TObject);
  2. begin
  3.   CreateLabelEditBox(Label1,@UpdateGameDetails(list, ListBox1.ItemIndex, gdTitle, edLabelEdit.text));
  4. end;
  5.  
  6.  

Code: Pascal  [Select][+][-]
  1. procedure TForm1.CreateLabelEditBox(aObject:TControl; aOnEditingDone: TNotifyEvent);
  2. begin
  3.   if edLabelEdit = nil then begin
  4.       edLabelEdit:=TEdit.Create(nil);
  5.       edLabelEdit.Left:=aObject.Left;
  6.       edLabelEdit.Top:=aObject.top;
  7.       edLabelEdit.BorderStyle:=bsNone;
  8.       edLabelEdit.Height:=aObject.Height;
  9.       edLabelEdit.Width:=aObject.Width;
  10.       edLabelEdit.Color:=RGBToColor(100,100,100);
  11.       edLabelEdit.OnEditingDone:=aOnEditingDone;
  12.       edLabelEdit.Font:=aObject.Font;
  13.       edLabelEdit.Parent:=self;
  14.       edLabelEdit.SetFocus;
  15.  
  16.   end
  17.   else begin
  18.       edLabelEdit.Left:=aObject.Left;
  19.       edLabelEdit.Top:=aObject.top;
  20.       edLabelEdit.Height:=aObject.Height;
  21.       edLabelEdit.Width:=aObject.Width;
  22.       edLabelEdit.OnEditingDone:=aOnEditingDone;
  23.       edLabelEdit.Font:=aObject.Font;
  24.       edLabelEdit.SetFocus;
  25.  
  26.   end;
  27.  
  28. end;
  29.  
But it Gives me Error: Variable identifier expected.  Please help :)

winni

  • Hero Member
  • *****
  • Posts: 3197
Re: Procedure with parameters as a parameter of procedure
« Reply #1 on: November 28, 2022, 08:00:38 pm »
Hi!

Help yourself:

The error message  tell you the line number and the column number, where the error occurs.

So you are able to place the cursor exact where the compiler howls.

In opposite to us.

Winni

dseligo

  • Hero Member
  • *****
  • Posts: 1222
Re: Procedure with parameters as a parameter of procedure
« Reply #2 on: November 28, 2022, 08:03:24 pm »
It won't work like that.

You have to declare your event like this:
Code: Pascal  [Select][+][-]
  1. procedure TForm1.UpdateGameDetails(Sender: TObject);

And you set it like this:
Code: Pascal  [Select][+][-]
  1. procedure TForm1.Label1Click(Sender: TObject);
  2. begin
  3.   CreateLabelEditBox(Label1,@UpdateGameDetails));
  4. end;

I don't know what you want to do exactly, but you have to think of another way to provide data to your event (maybe put it in a class when creating control or something like that).

Warfley

  • Hero Member
  • *****
  • Posts: 1499
Re: Procedure with parameters as a parameter of procedure
« Reply #3 on: November 29, 2022, 01:09:14 pm »
What you are trying to do in functional languages would be called partial application, where you take a function, fix the parameters and get a new function as a result that calls the existing function using those parameters.

In pascal this behavior can be approximated with function references, which are right now only available in the trunk of fpc. The problem is that you want to set an LCL event, and as far as I know they (currently) still use method pointers and not (the more generic) function references.

Thererfore, long story short, you can't do it this way. Potentially, as function references are just an interface internally, you can cast this to a method on that interface and this could work.

Here is how you need to do it right now (with current stable fpc): Create a new class which holds all the parameters for said function as fields. Then create you Method in that class that calls the function with the parameters stored as class fields

Code: Pascal  [Select][+][-]
  1. type
  2.   TUpdateGameDetailsCaller = class
  3.   private
  4.     FForm: TForm1;
  5.     FGamesList: TStringList;
  6.     FGameIndex: integer;
  7.     FGameDetail: TGameDetails;
  8.     FValue:string;
  9.   public
  10.     constructor Create(AForm: TForm1; GamesList: TStringList; aGameIndex: integer; aGameDetail: TGameDetails; aValue:string);
  11.     procedure Call(Sender: TObject);
  12.   end;
  13.  
  14. constructor TUpdateGameDetailsCaller.Create(AForm: TForm1; GamesList: TStringList; aGameIndex: integer; aGameDetail: TGameDetails; aValue:string);
  15. begin
  16.   FForm := AForm;
  17.   FGamesList := GamesList;
  18.   FGameIndex := aGameIndex;
  19.   FGameDetail := aGameDetail;
  20.   FValue:string := aValue;
  21. end;
  22.  
  23. procedure Call(Sender: TObject);
  24. begin
  25.   FForm.UpdateGameDetails(FGamesList, FGameIndex, FGameDetail, FValue)
  26. end;

And called with:
Code: Pascal  [Select][+][-]
  1.  CreateLabelEditBox(Label1,@TUpdateGameDetailsCaller.Create(list, ListBox1.ItemIndex, gdTitle, edLabelEdit.text).Call);

How to free the temporary object afterwards is something you can findout yourself. Thats the hard part (because manual memory management sucks)

 

TinyPortal © 2005-2018