Tiburon - Anonymous Methods

In Tiburon you will be able to work with anonymous methods, but what is it?

Anonymous method is a procedure or function that does not have a name associated with it. An anonymous method treats a block of code as an entity that can be assigned to a variable or used as a parameter to a method. In addition, an anonymous method can refer to variables and bind values to the variables in the context in which the method is defined.

Suppose you need to execute part of one code more them once, this code is only necessary in this method, you can define this code as anonymous, look the example below.

Anonymous Example

Simple and shorter the code is that uses anonymous methods. This is ideal if you want to explicitly and simply define these methods and use them immediately without the overhead and effort of creating a class that may never be used anywhere else. The resulting code is easier to understand.

A very important feature of anonymous methods is that they may reference variables that are visible to them where they were defined, these variables can be bound to values and wrapped up with a reference to the anonymous method.

Anonymous example - binding variable

The variable adder contains an anonymous method that binds the value 20 to the variable y referenced in the anonymous method’s code block. This binding persists even if the value goes out of scope.

Posted by Andreano Lanusse on July 17th, 2008 under Delphi, English |



23 Responses to “Tiburon - Anonymous Methods”

  1. Lars D Says:

    I assume that this is implemented this way: "MakeAdder:= " creates a new object of a hidden class type, which implements the anonymous method and has y as property. After that, it sets the value of y, and the Result of MakeAdder() is a pointer to function of anonymous object.

    It’s very cute - I look forward to see where the tradeoff between minimizing SLOC and ease of maintenance would favor using it.

  2. Steve Moran Says:

    Excellent. I can see how useful that would be. I guess these ideas are coming in from Ruby and Python. Maybe there could be an interpreted version of Delphi one day.

  3. Joe H Says:

    I’m not sure that anything that one has to struggle to follow is a benefit. When you name a procedure or function, that step in itself is a form of documentation. It’s cute not to be required to do that but I don’t think it will make code any more maintainable but looks to be a tool to enhance the ability to obfuscate and I sure don’t see where it saves any lines of code. I strive to make my code easily readable even though at this point I’m the only one who will read it. I can look at old pascal code I wrote many years ago and follow what’s going on with ease. The same is not true of C++ code I wrote and even less so for code that others have written.

    Personally I’d much rather see += and -= and other similar operator pairs that save a considerable amount of typing in many cases and do not make the code harder to read. That’s one of the only things in C/C++ that I particularly like.

  4. Ritsaert Says:

    Is the folowing also possible:

    MyStruct.Sort( function( A, B: Integer ): Integer; begin Result := B - A; end; );

  5. Anonymous Says:

    … + z ?

  6. Olaf Monien Says:

    @Ritsaert
    I don’t see any reason why this should NOT work. If Sort is declared as
    Sort(TSorter) and TSorter is declared as
    TSorter = reference to function(A,B:integer):integer;
    then your code would be valid syntax. It actually shows the power of this new language feature.

    Btw: I expect even more power if you combine that with Generics :)

  7. Olaf Monien Says:

    Typo:
    Sort should be defined as Sort(ASorter: TSorter)

  8. Kryvich Says:

    Delphi becomes C# for native applications?

    Just curious: why not use good old syntax
    type
    TFucnOfInt = function(x: Integer): Integer;
    instead of
    TFucnOfInt = reference to function(x: Integer): Integer;

  9. m. Th. Says:

    The method pointers are unified?

    Ie.

    TMyProc = reference to procedure(foo: integer);

    works also for both ‘bar’, ‘bar2′ and ‘bar3′ in the following example?

    procedure bar(foo: integer);

    and also for

    TMyClass = class
    procedure bar2(foo2: integer);
    end;

    procedure baz;

    var
    x: string; //whatever

    procedure bar3(foo3: integer); //nested one
    begin
    //LOC here
    end;

    begin
    //LOC
    end;

  10. Joao Henrique Levada Says:

    It would be better to provide the += operator and require the . (period) on the with statement than this.

  11. Ritsaert Says:

    That sounds good; thanks for the info.

  12. George Shen Says:

    Can anonymous methods deal with var parameters ?

  13. Maxim Says:

    The greatest addition to ObjectPascal along with generics and for..in loops.

    Congratulations!

    Just look at JavaScript closures. They are used in each and every JS toolkit. Java has a JSR for them as well.

    By the way, why "reference to"? Just to avoid generation af internal class and extended stack frame for each call and save "one-passess" of the compiler?

  14. Jolyon Smith Says:

    Echoing previous comments - what gives with the new "reference to" preamble?

    Utterly unnecessary as far as I can see, and a potential source of confusion. After all, why not:

    var
    o: reference to TObject;

    Just as redundant but at least consistent (with the new incantation). Or does the use of "reference to" confer some special properties on these types that is not present in "regular" function/procedure pointer types?

    It’s the only explanation I can think of.

    I also share similar concerns to those expressed w.r.t on-going maintenance of code that uses this stuff.

    Really, apart from the binding to local variables, what does this really offer that existing function pointers do not already provide in an arguably much clearer (certainly more easily understood) fashion?

    In C# (the aping of which is what ultimately lies behind this stuff) the need was clear, to avoid delegates and so streamline things. Here, the "solution" is less streamlined than what we already had (and still have?)

    As I understand things though, this was also needed in C# for the LINQ implementation (initially a huge piece of "WOW" functionality that is rapidly losing it’s appeal - and traction - as pointy sticks get prodded at it). Heck, even within Microsoft the great standard bearer for LINQ (LINQ for SQL) is looking a bit pathetic now that ADO Entities are here.

    If I recall, the local variable binding stuff is (partly at least) the LINQ connection in this area. And sure, it has real "cool - wow look at that value" when you look at trivial little demos. Put this sort of stuff into even slightly more than non-trivial production code however, and the price will be paid in spades when some poor sap has to come speluncking through the code in months/years time and try to figure out how to fix some bug or other.

    This is a BAD direction for Delphi to be going in, leading, as it does, right up to the door step of C#.

    If Delphi is to become just a Pascal imitator of C#, I think most people are just going to say "to hell with it - let’s just use C#. It’s Microsoft, and it’s on the front edge of the language curve, as opposed to this CodeGear C# wannabe, which is way behind the curve and, well, isn’t Microsoft. So what if C# is potentially slower, it’s so gosh-darn sexy. Phwoarr!"

    The great advantage that Delphi used to have was that it was just as powerful as C++ but a darn sight more pleasurable and productive to work with (on an on-going basis, rather than a "sexy toys to spew out code, and we’ll worry about the maintenance issues when they arise" basis).

    Ugly, inscrutable code is the order of the day in the C# camp, so new functionality that is also ugly and inscrutable at least fits comfortably in (especially when it cuts down on SOME of the existing ugliness and inscrutability).

  15. Caleb Says:

    If this works as described, then it means Delphi gets closures. "Anonymous methods" is a really silly name for this feature, because that is an artifact of the implementation, not the underlying feature itself. The real feature is the binding of local data inside method declarations. This is big in functional programming:

    http://en.wikipedia.org/wiki/Closure_(computer_science)

    There is a good deal of discussion about it on the net, but it is mostly with languages such as lisp, python, ruby, javascript, C# and so on.

    It is a technique for solving some kinds of problems efficiently, just like OOP is a technique for solving some other kinds of problems efficiently.

    Andreano, in Tiburon can we assign closures to delphi events if the calling signature matches? I expect this would be one of the more common uses.

  16. Andreano Lanusse Says:

    Caleb, this is a very good question. Days ago we had some discussion about that with Barry Kelly our compiler guy, here his answer.

    Method references are managed types, while events are method pointer-valued properties, and method pointers are unmanaged types. Thus, for type-safety reasons, assigning method references to method pointers is not supported.

    The primary motivation behind using method references is to have a type that can contain a closure value. Since closures close over their defining environment, including any local variables reference at the point of definition, they have state that must be freed. Method references, being managed types (they are reference counted), can keep track of this state and free it when necessary.

    If a method reference or closure could be freely assigned to a method pointer, such as an event, then ill-typed programs with dangling pointers or memory leaks would be very easy to create.

    The easiest and best, but possibly not most convenient, way to assign a method reference or closure value to an event is to ensure that the event a method reference type.

  17. Caleb Says:

    "is to ensure that the event a method reference type."

    I’m not sure what this means, but I get that direct assignment to event handler slots will not be possible. A pity.

  18. Andreano Lanusse Says:

    Yes, won’t be possible direct assignment to event handler

  19. Joe White Says:

    Wait. Does this mean we’ll be able to make a variable of type "reference to TFoo" and have the compiler automatically refcount it and clean it up, without needing to declare an interface?

    Or better yet, define "TFoo = reference to class…" and get the same automatic refcounting, with no need to FreeAndNil explicitly?

    Our modus operandi is to declare an interface for every new class we create, just so we don’t have to sweat the memory management. But I’d love to be able to do the same thing with less typing.

  20. Wim van Nifterick Says:

    In addition to what Joe H wrote: can anyone explain to me what the real advantage of anonymus methods over named ones? I would code the "adder" example as below (with a subroutine), which imho does the same job and is much clearer. I’m probably missing the point.

    function VeryComplicateFunction(const x,y:integer):integer;
    begin
    // hundreds LOC, but for simplicity like in the example:
    Result := x + y;
    end; // VeryComplicateFunction

    //**************************************************************

    procedure TFOO.DoTheTest;
    var
    MyNumber : integer;

    //————————————————————–

    {sub}function SimpleFunction(const Number:integer):integer
    begin
    Result:=VeryComplicateFunction(MyNumber,Number);
    end; // SimpleFunction in DoTheTest

    //————————————————————–

    begin
    MyNumber:=20;
    Writeln(SimpleFunction(22)); // writes 42
    end; // DoTheTest

    //**************************************************************

  21. Craig Stuntz’s Weblog : Understanding Anonymous Methods Says:

    [...] to the Delphi roadmap, anonymous methods will be assignable to procedure references.  You can see an example of this on Andreano Lanusse’s [...]

  22. bart roozendaal Says:

    I’m afraid I’m with the sceptical people out there. I don’t see the value in this all. Looking at the examples out there, and even this one, it simply makes the code more complex (to read) and the things shown with the examples are very doable using the OO techniques that we currently have.

    Others may like this; I’m glad I don’t need to use them if I don’t want to.

  23. El Cy Says:

    It is just me (don’t want to offend anybody !!!) … but also CodeGear guys (maybe excepting Barry) … are also puzzled by the new Delphi addition: closures….

    Until a very good usage scenario (maybe inspired from C#, JavaScript, Ruby, Groovy…etc) of closures will not be provided (adapted to Delphi) … we will just continue to be biased against the creepy syntax :)

    I just assume that anon-methods (closures) were added to Delphi (currently just in Win32/ no .NET mention) to align to the current modern language features (.NET family + dynamic ones) and also to support future devel as native Delphi Linq-like syntax sugar [maybe using sets ?] and future C++0x lambdas… Just a guess…

    Barry just promised us some real-word examples for Delphi closures … so lets press Barry for releasing these gems :)

Leave a Comment


Server Response from: dnrh2.codegear.com

 
© Copyright 2008 Embarcadero Technologies, Inc. All Rights Reserved. Contact Us  |   Site Map  |   Legal Notices  |   Privacy Policy  |   Report Software Piracy