What issue does "reference to" solve
Asked Answered
R

2

6

On Chris's blog: http://delphihaven.wordpress.com/2011/07/14/weird-in-more-ways-than-one/

I found the following code

type
  TLinkVisitor<T> = reference to procedure(const Item: T);

  TDoubleLinked<T> = record
    Prev: ^TDoubleLinked<T>;
    Next: ^TDoubleLinked<T>;
    Value: T;
    class function Create(const aValue: T): Pointer; static;
    function Add(const aValue: T): Pointer;
    procedure Delete;
    procedure DeleteAll;
    function First: Pointer;
    function Last: Pointer;
    procedure ForEach(const Proc: TLinkVisitor<T>);
  end;

What problem does the 'reference to' keyword solve that cannot be done with a normal procedural type?

Radiate answered 4/5, 2014 at 21:13 Comment(0)
V
11

With a reference procedure you can use:

  • A traditional procedure, or
  • A method of an object, class or record, or
  • An anonymous method.

It is the capacity to work with anonymous methods that sets reference procedures apart from all other procedural types. And what sets anonymous methods apart from other procedural or method types is variable capture.

For a more detailed discussion refer to this answer: What is the difference between of object and reference to?. The official documentation for anonymous methods is also worth reading.

Veranda answered 4/5, 2014 at 21:16 Comment(0)
R
4

According to the official documentation the problem (to be solved) is that anonymous methods are managed types, whereas procedural variables are not.
The 'reference to' keyword is more general than the other procedural types.

Here's how the doc puts it: http://docs.embarcadero.com/products/rad_studio/delphiAndcpp2009/HelpUpdate2/EN/html/devcommon/anonymousmethods_xml.html

Anonymous methods are typically assigned to something, as in these examples:

myFunc := function(x: Integer): string
begin
  Result := IntToStr(x);
end;

myProc := procedure(x: Integer)
begin
  Writeln(x);
end;

Anonymous methods may also be returned by functions or passed as values for parameters when calling methods. For instance, using the anonymous method variable myFunc defined just above:

type
  TFuncOfIntToString = reference to function(x: Integer): string; 

procedure AnalyzeFunction(proc: TFuncOfIntToString); 
begin 
  { some code } 
end;

// Call procedure with anonymous method as parameter 
// Using variable: 
AnalyzeFunction(myFunc);

// Use anonymous method directly: 
AnalyzeFunction(function(x: Integer): string 
begin 
  Result := IntToStr(x); 
end;) 

Method references can also be assigned to methods as well as anonymous methods. For example:

type
  TMethRef = reference to procedure(x: Integer);
TMyClass = class
  procedure Method(x: Integer);
end;

var
  m: TMethRef;
  i: TMyClass;
begin
  // ...
  m := i.Method;   //assigning to method reference
end;

However, the converse is not true: you can't assign an anonymous method to a regular method pointer. Method references are managed types, but method pointers are unmanaged types. Thus, for type-safety reasons, assigning method references to method pointers is not supported. For instance, events are method pointer-valued properties, so you can't use an anonymous method for an event. See the section on variable binding for more information on this restriction.

Radiate answered 4/5, 2014 at 21:35 Comment(2)
You are missing one of the most important key features of anonymous methods which is variable capturing. Other things like passing around or returning them can be done with regular function pointers but variable capturing cannot.Niedersachsen
Thanks @StefanGlienke for pointing that out. I'd forgotten all about that. Of course all of this fanciness happening on the heap rules out this stuff for high speed code.Radiate

© 2022 - 2024 — McMap. All rights reserved.