Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What issue does "reference to" solve

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?

like image 790
Johan Avatar asked May 04 '14 21:05

Johan


2 Answers

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.

like image 120
David Heffernan Avatar answered Oct 18 '22 23:10

David Heffernan


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.

like image 22
Johan Avatar answered Oct 18 '22 23:10

Johan