Recent

Author Topic: Defer Mechanism for FreePascal  (Read 6514 times)

Sniper

  • New Member
  • *
  • Posts: 39
Defer Mechanism for FreePascal
« on: June 26, 2021, 12:16:28 pm »
Everybody who writes in Golang know about it's defer mechanism.

I found proposal of this useful thing for C (C2x)

http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2542.pdf

Do FPC core developers are interested in "defer" mechanism in freepascal?

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 11444
  • FPC developer.
Re: Defer Mechanism for FreePascal
« Reply #1 on: June 26, 2021, 01:31:17 pm »
Sound like procedural form of exception handling. We already have such things in try.except and try.finally.

Bi0T1N

  • Jr. Member
  • **
  • Posts: 85
Re: Defer Mechanism for FreePascal
« Reply #2 on: June 26, 2021, 01:49:16 pm »
Sound like procedural form of exception handling. We already have such things in try.except and try.finally.
I think that was also the outcome of the thread on the mailing list.

PascalDragon

  • Hero Member
  • *****
  • Posts: 5462
  • Compiler Developer
Re: Defer Mechanism for FreePascal
« Reply #3 on: June 27, 2021, 01:11:53 pm »
Sound like procedural form of exception handling. We already have such things in try.except and try.finally.
I think that was also the outcome of the thread on the mailing list.

Correct. There is no need for a defer. A tryfinally might be more verbose, but why sugar coat it?
Also e.g. Lazarus helps you out there quite a bit by completing a try to a tryfinally, a tryf to a tryfinally with the cursor in the finally-block and a trye to a tryexcept. And then there's the nifty trycf which will create the following code:

Code: Pascal  [Select][+][-]
  1. VarName := TMyClassName.Create;
  2. try
  3.              
  4. finally
  5.   VarName.Free;
  6. end;

Where the IDE highlights VarName and TMyClassName as editable blocks you can switch between with Tab (and editing VarName will edit both locations).

AlexTP

  • Hero Member
  • *****
  • Posts: 2399
    • UVviewsoft
Re: Defer Mechanism for FreePascal
« Reply #4 on: June 27, 2021, 01:29:35 pm »
@PascalDragon,
thanks for pointing that out. Offtopic: I am your fan, trying to read all your last messages. :)

Bogen85

  • Hero Member
  • *****
  • Posts: 595
Re: Defer Mechanism for FreePascal
« Reply #5 on: November 19, 2022, 10:26:28 pm »
I know this an old post, but this can be done in FPC 3.3.1+.

If Free Pascal has defer functionality was just asked in the Unofficial Free Pascal chat on discord so I thought I'd provide the same answer here.

defer.pas
Code: Pascal  [Select][+][-]
  1. {$mode objfpc}{$H+}
  2. {$modeswitch anonymousfunctions}
  3. {$modeswitch functionreferences}
  4. {$modeswitch advancedrecords}
  5.  
  6. unit defer;
  7.  
  8. interface
  9.  
  10. type
  11.   tDeferProc = reference to procedure;
  12.   tDeferred = array of tDeferProc;
  13.   tDefer = record
  14.   strict private
  15.     deferred: tDeferred;
  16.     class operator finalize (var self: tDefer);
  17.     class operator initialize (var self: tDefer);
  18.     procedure assign (const _deferred: tDeferProc);
  19.   public
  20.     property x: tDeferProc write assign;
  21.   end;
  22.  
  23. implementation
  24.  
  25. class operator tDefer.finalize (var self: tDefer);
  26.   var
  27.     i: integer;
  28.   begin
  29.     for i := high(self.deferred) downto low(self.deferred) do self.deferred[i]();
  30.   end;
  31.  
  32. class operator tDefer.initialize (var self: tDefer);
  33.   begin
  34.     self.deferred := [];
  35.   end;
  36.  
  37. procedure tDefer.assign (const _deferred: tDeferProc);
  38.   begin
  39.     insert(_deferred, deferred, length(deferred));
  40.   end;
  41.  
  42. begin
  43. end.

main.pas
Code: Pascal  [Select][+][-]
  1. {$mode objfpc}
  2. {$H+}
  3. {$modeswitch anonymousfunctions}
  4. {$modeswitch functionreferences}
  5.  
  6. program main;
  7.  
  8. uses
  9.   defer,
  10.   sysutils;
  11.  
  12.   procedure main;
  13.     var
  14.       defer: tDefer;
  15.       y:     integer;
  16.  
  17.     procedure deferred;
  18.       begin
  19.         inc(y);
  20.         writeln(format('Goodbye World! y = %d', [y]));
  21.       end;
  22.  
  23.     begin
  24.       y       := 4;
  25.       defer.x := procedure
  26.       begin
  27.         writeln('First added runs last! y=', y);
  28.       end;
  29.  
  30.       defer.x := procedure
  31.       begin
  32.         writeln('Last added runs first! y=', y);
  33.       end;
  34.  
  35.       defer.x := tDeferProc(@deferred);
  36.       writeln('Hello, World!');
  37.       writeln(format('y : %d', [y]));
  38.     end;
  39.  
  40. begin
  41.   main;
  42. end.

Code: Text  [Select][+][-]
  1. $ fpc main.pas
  2. Free Pascal Compiler version 3.3.1 [2022/11/19] for x86_64
  3. Copyright (c) 1993-2022 by Florian Klaempfl and others
  4. Target OS: Linux for x86-64
  5. Compiling main.pas
  6. Linking main
  7. 45 lines compiled, 0.2 sec, 375712 bytes code, 167784 bytes data
  8. Sat 19Nov22 15:16:11 /home/dev/das_misc/sandbox-scratch/defer
  9.  
  10. $ ./main
  11. Hello, World!
  12. y : 4
  13. Goodbye World! y = 5
  14. Last added runs first! y=5
  15. First added runs last! y=5
  16.  

So if someone is looking for something akin to defer from other languages:
https://github.com/vlang/v/blob/master/doc/docs.md#defer
https://golangbot.com/defer/ that can be approximated in Free Pascal.

(By either providing a function to defer or code to defer execution of, then the above code demonstrates how that can be done).


« Last Edit: November 19, 2022, 10:38:22 pm by Bogen85 »

PascalDragon

  • Hero Member
  • *****
  • Posts: 5462
  • Compiler Developer
Re: Defer Mechanism for FreePascal
« Reply #6 on: November 19, 2022, 10:48:23 pm »
Please note that FPC does in no way guarantee when exactly a managed type is finalized. It can be at the end of the function (line 38 of your example program) or directly after its last use (between line 35 and 36 of the example program). It's only guaranteed that it's finalized at the latest at the end of the scope.

Bogen85

  • Hero Member
  • *****
  • Posts: 595
Re: Defer Mechanism for FreePascal
« Reply #7 on: November 19, 2022, 11:08:14 pm »
Please note that FPC does in no way guarantee when exactly a managed type is finalized. It can be at the end of the function (line 38 of your example program) or directly after its last use (between line 35 and 36 of the example program). It's only guaranteed that it's finalized at the latest at the end of the scope.

Understood.
So from what I understand an empty placeholder method could be added to the defer managed type, to anchor the calls to the bottom of the scope.

Code: Pascal  [Select][+][-]
  1. ...
  2.   public
  3.     property x: tDeferProc write assign;
  4.     procedure anchor;
  5.   end;
  6.  
  7. implementation
  8.  
  9. procedure tDefer.anchor;
  10.   begin
  11.   end;
  12. ...
  13.  

And when used:

Code: Pascal  [Select][+][-]
  1. begin
  2.   ...
  3.   defer.anchor; // placed right before final end;
  4. end;
  5.  
« Last Edit: November 19, 2022, 11:40:02 pm by Bogen85 »

Bogen85

  • Hero Member
  • *****
  • Posts: 595
Re: Defer Mechanism for FreePascal
« Reply #8 on: November 19, 2022, 11:46:28 pm »
Please note that FPC does in no way guarantee when exactly a managed type is finalized. It can be at the end of the function (line 38 of your example program) or directly after its last use (between line 35 and 36 of the example program). It's only guaranteed that it's finalized at the latest at the end of the scope.

Thanks for pointing that out!

Same here:
@PascalDragon,
Offtopic: I am your fan, trying to read all your last messages. :)
;D ;D

PascalDragon

  • Hero Member
  • *****
  • Posts: 5462
  • Compiler Developer
Re: Defer Mechanism for FreePascal
« Reply #9 on: November 20, 2022, 12:12:23 am »
Please note that FPC does in no way guarantee when exactly a managed type is finalized. It can be at the end of the function (line 38 of your example program) or directly after its last use (between line 35 and 36 of the example program). It's only guaranteed that it's finalized at the latest at the end of the scope.

Understood.
So from what I understand an empty placeholder method could be added to the defer managed type, to anchor the calls to the bottom of the scope.

Yes, that would work.

Also an additional remark for your code: the Initialize operator is not required, because dynamic arrays are always initialized to an empty array anyway.

Bogen85

  • Hero Member
  • *****
  • Posts: 595
Re: Defer Mechanism for FreePascal
« Reply #10 on: November 20, 2022, 12:17:16 am »
Yes, that would work.

Thanks for clarification.

Also an additional remark for your code: the Initialize operator is not required, because dynamic arrays are always initialized to an empty array anyway.

Thanks as well!

Bogen85

  • Hero Member
  • *****
  • Posts: 595
Re: Defer Mechanism for FreePascal
« Reply #11 on: November 20, 2022, 01:03:44 am »

Thaddy

  • Hero Member
  • *****
  • Posts: 14357
  • Sensorship about opinions does not belong here.
Re: Defer Mechanism for FreePascal
« Reply #12 on: November 20, 2022, 09:31:38 am »
Note that is it is not a good idea to name your unit defer and subsequently in main a variable that is also called defer, while also having a defer in the uses clause.
I would change the unit name in this case, suggest fpcdefer, deferrer or something.
It is not knit-picking. Such name clashes can bite.

But it is very neat code, may come in useful.
« Last Edit: November 20, 2022, 09:45:24 am by Thaddy »
Object Pascal programmers should get rid of their "component fetish" especially with the non-visuals.

Bogen85

  • Hero Member
  • *****
  • Posts: 595
Re: Defer Mechanism for FreePascal
« Reply #13 on: November 20, 2022, 09:51:27 am »
Note that is it is not a good idea to name your unit defer and subsequently in main a variable that is also called defer, while also having a defer in the uses clause.
I would change the unit name in this case, suggest fpcdefer, deferrer or something.

I made the unit name change, from defer to fpcdefer.

It is not knit-picking. Such name clashes can bite.

Agreed. I appreciate the feedback.

But it is very neat code, may come in useful.

Thanks!


AlexTP

  • Hero Member
  • *****
  • Posts: 2399
    • UVviewsoft
Re: Defer Mechanism for FreePascal
« Reply #14 on: November 20, 2022, 10:32:59 am »
@bogen85
Why to add 'property x', better to add 'procedure Add'.

 

TinyPortal © 2005-2018