Recent

Author Topic: [CLOSED (almost)] Mixed "procedure" and "procedure of object" callback  (Read 14577 times)

lucamar

  • Hero Member
  • *****
  • Posts: 4217
Re: Mixed "procedure" and "procedure of object" callback
« Reply #15 on: April 20, 2020, 12:58:44 pm »
Yeah. Closures are actually the best way to do it:

Actually, the closure adds little to your example; it's the reference declaration that does everything there (and allows the unnamed function to work), but AFAIK Free Pascal hasn't got that kind of procedural type declaration.

As for Thaddy's suggestion, it's good to know the thing about static class methods but it doesn't really helps in this case. The point was to simplify the suggested solution; yours, though, would at the very least entail subclassing TFileSearcher and making sundry modifications that would end up complicating matters.

The point was (as an example) building a substitute FindAllFiles() with a procedural parameter to be called for each file found. The original FindAllFiles() uses a TFileSearcher, so passing a method to it is as simple as setting a property with the parameter. The complication comes because we want to be able to use also a normal procedure.

The easy solution is to use an intermediate event handler in the implementation which will be used to call the "normal" procedure when we use that variant, but then we would need an "implementation" global. I was hoping to find a more simple way to do it, without subclassing TFileSearcher or complicating matters much more.

But it seems what I already found (save for some details) is the most simple. ;)
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus/FPC 2.0.8/3.0.4 & 2.0.12/3.2.0 - 32/64 bits on:
(K|L|X)Ubuntu 12..18, Windows XP, 7, 10 and various DOSes.

Thaddy

  • Hero Member
  • *****
  • Posts: 18764
  • To Europe: simply sell USA bonds: dollar collapses
Re: Mixed "procedure" and "procedure of object" callback
« Reply #16 on: April 20, 2020, 01:18:45 pm »
As for Thaddy's suggestion, it's good to know the thing about static class methods but it doesn't really helps in this case. The point was to simplify the suggested solution; yours, though, would at the very least entail subclassing TFileSearcher and making sundry modifications that would end up complicating matters.
That should not be the case.
If Europe sells their USA bonds the USD will collapse. Europe can affort that given average state debts. The USA can't affort that. Just an advice...

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 12172
  • Debugger - SynEdit - and more
    • wiki
Re: Mixed "procedure" and "procedure of object" callback
« Reply #17 on: April 20, 2020, 01:19:39 pm »
Instead of your overloads you can have operators

I didn't though of operators, thanks Martin. Just one thing: would that allow me to have just a single function FindAllFiles(..., const Callback: TCallback) and call it passing either a normal proc or a method param? I mean, will the compiler select the correct operator for each to build the record?

Yes, it will. (Assuming you have no ambiguous overloads for the function).



PascalDragon

  • Hero Member
  • *****
  • Posts: 6349
  • Compiler Developer
Re: Mixed "procedure" and "procedure of object" callback
« Reply #18 on: April 20, 2020, 01:19:59 pm »
Instead of your overloads you can have operators

I didn't though of operators, thanks Martin. Just one thing: would that allow me to have just a single function FindAllFiles(..., const Callback: TCallback) and call it passing either a normal proc or a method param? I mean, will the compiler select the correct operator for each to build the record?

I've to confess I'm not that much conversant with operator overloads ... :-[

Yes, the compiler will pick the correct overload (at least if no bugs are involved :-X ).

In addition to Martin's remark:
a static class procedure has no hidden self and is compatible with a normal procedure or function.

But unfortunately pointless for that exact same reason, since the callback wouldn't get any SELF. You might as well just allow a procedure then.
Not really pointless, as you can:
- use a var parameter to simulate self if needed. (similar how advanced record operators work)
- it is still information hiding from and over globals. E.g. callbacks can be better defined in the class where they belong.
E.g.:
Code: Pascal  [Select][+][-]
  1.  Class procedure TFilesearcher.MyCallback(var value:TFileSearcher;const FileToSearch:string);static;
  2.  // basically the same as a global procedure like:
  3.  procedure MyCallback(var value:TFileSearcher;const FileToSearch:string);

Modify to your liking. Add salt and pepper to taste. This has the same signature as a global procedure, but is tied to the class and has no hidden self.
I think this is basically what lucamar wants?

It is in no way guaranteed that Self is passed as the first argument. It totally depends on the ABI (for example in MSVC C++ on i386 this is passed in ECX, but no ordinary parameter is ever passed in ECX (in that calling convention), so you wouldn't be able to use that trick there).

lucamar

  • Hero Member
  • *****
  • Posts: 4217
Re: Mixed "procedure" and "procedure of object" callback
« Reply #19 on: April 20, 2020, 01:24:49 pm »
Thanks, Martin (and PascalDragon). Looks like I need to study quite a lot about operators, helpers and all those "new flanged" things :D
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus/FPC 2.0.8/3.0.4 & 2.0.12/3.2.0 - 32/64 bits on:
(K|L|X)Ubuntu 12..18, Windows XP, 7, 10 and various DOSes.

Mr.Madguy

  • Hero Member
  • *****
  • Posts: 881
Re: Mixed "procedure" and "procedure of object" callback
« Reply #20 on: April 20, 2020, 02:12:58 pm »
Actually, the closure adds little to your example; it's the reference declaration that does everything there (and allows the unnamed function to work), but AFAIK Free Pascal hasn't got that kind of procedural type declaration.
As I know, closures are constantly promised to be implemented in latest FPC builds. If they aren't yet, then it's major FPC problem, because 2009 was 11 years ago and FPC still isn't compatible with Delphi 2009. Closures are extremely powerful. They allow you to declare interfaced objects...without actually declaring interfaced objects.

I personally would want to also see multiple inheritance support. At least virtual multiple inheritance. Don't tell me, that I can avoid it. I can, but it would be ugly crutch. Tools like this aren't about "I just want to use that things, because they exist in my compiler". They're about making programmer's work more effective, i.e. about achieving the same goal via wasting lesser number of code lines. And while it doesn't matter in simple homebrew projects, it does in big complex projects, that have thousands of lines of code. And while FPC doesn't support big complex projects - it will never be treated as professional tool.

Simple thing - compiler automatically adds wrappers for callbacks, that aren't closures. I.e this
Code: Pascal  [Select][+][-]
  1. function StaticCallback:Boolean;
  2. begin
  3. end;
  4.  
  5. MyProcedure(StaticCallback);
  6.  
actually turns into this
Code: Pascal  [Select][+][-]
  1. MyProcedure(
  2.   function:Boolean
  3.   begin
  4.     Result := StaticCallback;
  5.   end
  6. );
  7.  
But it doesn't for StaticCallback -> ObjectCallback, while it should be possible. And I've shown it in my first example. As procedure of object - is just Object-Procedure pair, so when it's called, it's just Procedure^(Object{i.e. Self}, ...). If procedure is static and doesn't require Self - it can be set to nil. Problem is - if procedure is called directly, then lack of first parameter Self can mess other parameters. This can happen in case of passing Self via stack. Wrapper procedure is needed in this case. I.e. compiler should automatically declare this:
Code: Pascal  [Select][+][-]
  1. function Wrapper_StaticCallback(Self:TObject):Boolean;
  2. begin
  3.   Result := StaticCallback;
  4. end;
  5.  
  6. MyProcedure(Wrapper_StaticCallback);
  7.  
« Last Edit: April 20, 2020, 02:31:27 pm by Mr.Madguy »
Is it healthy for project not to have regular stable releases?
Just for fun: Code::Blocks, GCC 13 and DOS - is it possible?

440bx

  • Hero Member
  • *****
  • Posts: 6123
Re: Mixed "procedure" and "procedure of object" callback
« Reply #21 on: April 20, 2020, 03:13:39 pm »
I can, but it would be ugly crutch.
Well... seems to me that avoiding multiple inheritance would result in code that is a lot cleaner, easier to understand and less prone to ambiguities (e.g, diamond of death)

And while FPC doesn't support big complex projects - it will never be treated as professional tool.
I find that comment surprising.  FPC itself, the compiler, is a fairly complex project.  What's your definition of a "complex project" ?

I haven't been shy of making my dislike for OOP evident in the past and your comments simply reinforce the reasons why I dislike it.  It seems OOP programmers want to add more and more rather questionable (read: poor) features into the compiler as a way out of the mess they got themselves into.
FPC v3.2.2 and Lazarus v4.0rc3 on Windows 7 SP1 64bit.

Mr.Madguy

  • Hero Member
  • *****
  • Posts: 881
Re: Mixed "procedure" and "procedure of object" callback
« Reply #22 on: April 20, 2020, 03:28:24 pm »
Well... seems to me that avoiding multiple inheritance would result in code that is a lot cleaner, easier to understand and less prone to ambiguities (e.g, diamond of death)
Short explanation: method overriding is ugly, when using class composition to avoid multiple inheritance. And while it's acceptable for class, that has 3-5 methods, it isn't for class, that can have 100 methods.
Code: Pascal  [Select][+][-]
  1. TClass1 = class
  2.   procedure Method;virtual;abstract;
  3. end;
  4.  
  5. TClass2 = class(TClass1)
  6.   procedure Method;override;
  7. end;
  8.  
turns into
Code: Pascal  [Select][+][-]
  1. TClass1 = class
  2.   procedure Method;virtual;abstract;
  3. end;
  4.  
  5. TClass2 = class
  6.   procedure Method;
  7. end;
  8.  
  9. TClass3 = class(TClass1)
  10.   FClass2:TClass2;
  11.   procedure Method;override;
  12. end;
  13.  
  14. procedure TClass3.Method;
  15. begin
  16.   FClass2.Method;
  17. end;
  18.  
See the difference? Code is 2x longer.
Is it healthy for project not to have regular stable releases?
Just for fun: Code::Blocks, GCC 13 and DOS - is it possible?

440bx

  • Hero Member
  • *****
  • Posts: 6123
Re: Mixed "procedure" and "procedure of object" callback
« Reply #23 on: April 20, 2020, 03:35:31 pm »
See the difference? Code is 2x longer.
Yes, I see your point but, I don't like the problems multiple inheritance opens the door to. 

FPC v3.2.2 and Lazarus v4.0rc3 on Windows 7 SP1 64bit.

Mr.Madguy

  • Hero Member
  • *****
  • Posts: 881
Re: Mixed "procedure" and "procedure of object" callback
« Reply #24 on: April 20, 2020, 03:44:23 pm »
Yes, I see your point but, I don't like the problems multiple inheritance opens the door to.
I just think, that diamond of death problem can be avoided. Via calling constructors in right order manually for example. But feel the power of virtual multiple inheritance!
Code: Pascal  [Select][+][-]
  1. TClass1 = class
  2.   procedure Method;virtual;abstract;
  3. end;
  4.  
  5. TClass2 = class(TClass1:virtual)
  6.   procedure Method;override;
  7. end;
  8.  
  9. TClass3 = class(TClass1:virtual, TClass2:override);
  10.  
Is it healthy for project not to have regular stable releases?
Just for fun: Code::Blocks, GCC 13 and DOS - is it possible?

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 12172
  • Debugger - SynEdit - and more
    • wiki
Re: Mixed "procedure" and "procedure of object" callback
« Reply #25 on: April 20, 2020, 05:22:12 pm »
And while FPC doesn't support big complex projects - it will never be treated as professional tool.

Strange, I always thought the fpc compiler was compiled with fpc itself. And the Lazarus IDE too.
But it can't be the case. Both of them are definitely "big complex projects".

;)

Otto

  • Full Member
  • ***
  • Posts: 226
Re: Mixed "procedure" and "procedure of object" callback
« Reply #26 on: April 20, 2020, 05:42:39 pm »
Hello 440bx.

I haven't been shy of making my dislike for OOP evident in the past and your comments simply reinforce the reasons why I dislike it.  It seems OOP programmers want to add more and more rather questionable (read: poor) features into the compiler as a way out of the mess they got themselves into.
The attempt to simplify complex systems by dividing the single system into reusable subsystems is one of the main purposes for which the oop paradigm was established. Not everything is always going well, so sometimes we have to find alternative solutions.
Probably the next step will be to use multi-paradigm programming languages.

 
Kind regards.

Mr.Madguy

  • Hero Member
  • *****
  • Posts: 881
Re: Mixed "procedure" and "procedure of object" callback
« Reply #27 on: April 20, 2020, 05:47:37 pm »
Diamond of death is 100% avoidable. Via rising "Ambiguous X" error and forcing programmer to resolve it. And we already have syntax for it. Such as this:
Code: Pascal  [Select][+][-]
  1.   TClass.Method(X, Y, Z);//Ambiguous method call
  2.   IInterface.Method = ClassMethod;//Ambiguous method override
  3.  
Is it healthy for project not to have regular stable releases?
Just for fun: Code::Blocks, GCC 13 and DOS - is it possible?

440bx

  • Hero Member
  • *****
  • Posts: 6123
Re: Mixed "procedure" and "procedure of object" callback
« Reply #28 on: April 20, 2020, 05:55:23 pm »
Hello Otto,

The attempt to simplify complex systems by dividing the single system into reusable subsystems is one of the main purposes for which the oop paradigm was established.
I don't think it accomplishes that.  My experience is, OOP creates a lot more problems than the few it solves.  One thing is for sure, it's a huge bag of syntactic sugar that caters very well to programmers who are allergic to pointers.  It has that going for it which may account for its wide acceptance.

Not everything is always going well, so sometimes we have to find alternative solutions.
To me that's a tell-tale sign that the solution isn't quite as good as originally thought.  When a solution is genuinely good, the code becomes simple and everything falls in place naturally.  When the solution is "questionable" more and more problems arise that require "alternatives".

Probably the next step will be to use multi-paradigm programming languages.
Honestly, I don't know if that is a way to simple, easy to understand code, it may be.  I'll have to see that implemented to have an opinion.
FPC v3.2.2 and Lazarus v4.0rc3 on Windows 7 SP1 64bit.

Otto

  • Full Member
  • ***
  • Posts: 226
Re: Mixed "procedure" and "procedure of object" callback
« Reply #29 on: April 20, 2020, 07:36:42 pm »
 To return to the thread's original question, I believe that it can be solved through anonymous functions (also called lambda functions), in Delphi or in C#, they are used to solve similar problems. Of course, there will be some equally good alternative solutions. As soon as the anonymous functions are introduced in FPC it will also be easier to convert written codes into languages that use them in FPC.


@440bx

I wouldn't want to go off topic, so I'll try to be concise. I have an open attitude towards programming paradigms, in the sense that I try to use the paradigm that in the language I'm using at that time solves, in my opinion, a certain problem at its best. Of course, if the needs change in the course of development, I would sometimes also have to rewrite a lot of the code. When I can decide which language to write programs in, I always choose Delphi or FPC; because, in my opinion, they
« Last Edit: April 20, 2020, 07:40:14 pm by Otto »
Kind regards.

 

TinyPortal © 2005-2018