Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-pascal / 2021-08

Better way to handle callback types

7 messages · 3 people ·

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Ryan Joseph

FPC has a number of function pointer types and eventually will have another in "reference to" closures. This presents a problem of how the programmer can make a function that is type agnostic so that we can use different types of callbacks.

Currently this is the best solution I can think of but it's still a real mess and tedious to setup. Here's a little snippet of a list class that has a Sort method.

It feels to me like the compiler needs a new type which wraps all the callbacks for us but maybe there's a better way?

========================================

type
  generic TSList<T> = class
  type
     TComparator = record
        private type
          TFuncProc = function (constref left, right: T; context: pointer): integer;
          TFuncNested = function (constref left, right: T; context: pointer): integer is nested;
          TFuncObject = function (constref left, right: T; context: pointer): integer of object;
        private
          index: TFuncType;
        public
          function Call(constref left, right: T; context: pointer): integer;
        case byte of
          0: (proc: TFuncProc);
          1: (nested: TFuncNested);
          2: (obj: TFuncObject);
      end;
     ...
      procedure Sort(callback: TComparator.TFuncProc; context: pointer = nil);
      procedure Sort(callback: TComparator.TFuncNested; context: pointer = nil);
      procedure Sort(callback: TComparator.TFuncObject; context: pointer = nil);
  end;
     ...
procedure TSList.Sort(callback: TComparator.TFuncProc; context: pointer);
var
  comparator: TComparator;
begin
  comparator.proc := callback;
  comparator.index := TFuncType.IsProc;
  { do sorting and call comparator.Call(left, right, context); which routes to the correct callback }
end;

Regards,
Ryan Joseph

Jonas Maebe
to Ryan Joseph
Ryan Joseph wrote 7 lines
type generic TSList<T> = class type TComparator = record private type TFuncProc = function (constref left, right: T; context: pointer): integer; TFuncNested = function (constref left, right: T; context: pointer): integer is nested;

You can pass global functions to "is nested" procvars, so at least these two don't need to be separate.

OTOH, there's another type: cblocks :)

Jonas

Ryan Joseph
to Jonas Maebe
Show quoted text 6 lines
On Aug 21, 2021, at 12:08 PM, Jonas Maebe via fpc-pascal wrote: You can pass global functions to "is nested" procvars, so at least these two don't need to be separate. OTOH, there's another type: cblocks :)

So up to 4 types are needed: "is nested", "of object" and "reference to" (for cblocks and eventually closures). Ouch.

This is certainly a mess and results in tons of boiler plate for functions that use callbacks. Shouldn't the compiler have a meta-type like I made? We should be able to write a single function which takes a callback and then have the compiler figure out which type is provided on the caller side.

Regards,
Ryan Joseph

Michael Van Canneyt
to Ryan Joseph
Ryan Joseph wrote 10 lines
> On Aug 21, 2021, at 12:08 PM, Jonas Maebe via fpc-pascal wrote: > > You can pass global functions to "is nested" procvars, so at least these > two don't need to be separate. > > OTOH, there's another type: cblocks :) So up to 4 types are needed: "is nested", "of object" and "reference to" (for cblocks and eventually closures). Ouch.

"Reference to" can be used for the others as well.

Michael.

Ryan Joseph
to Michael Van Canneyt
On Aug 21, 2021, at 1:30 PM, Michael Van Canneyt wrote: "Reference to" can be used for the others as well.

How do you mean? Reference to is currently only available for cblocks on macOS I think so I'm not sure how this would look.

Regards,
Ryan Joseph

Michael Van Canneyt
to Ryan Joseph
Ryan Joseph wrote 7 lines
> On Aug 21, 2021, at 1:30 PM, Michael Van Canneyt wrote: > > "Reference to" can be used for the others as well. How do you mean? Reference to is currently only available for cblocks on macOS I think so I'm not sure how this would look.

As in Delphi 'reference to' will also be used for all references where an anonymous functon can be used. But you can perfectly use methods and local functions for that. So it will function a like a catch-all procedural type.

When Sven is done with the anonymous methods, you'll see it in action.

Michael.

Ryan Joseph
to Michael Van Canneyt
Show quoted text 7 lines
On Aug 21, 2021, at 3:09 PM, Michael Van Canneyt via fpc-pascal wrote: As in Delphi 'reference to' will also be used for all references where an anonymous functon can be used. But you can perfectly use methods and local functions for that. So it will function a like a catch-all procedural type. When Sven is done with the anonymous methods, you'll see it in action.

But isn't this going to make the interface wrapper and allocate a class? Maybe Sven can explain how that works.

Regards,
Ryan Joseph