{"id":48,"date":"2008-08-04T21:16:12","date_gmt":"2008-08-04T09:16:12","guid":{"rendered":"https:\/\/www.deltics.co.nz\/blog\/?p=48"},"modified":"2009-08-07T13:36:04","modified_gmt":"2009-08-07T01:36:04","slug":"anonymous-methods-when-should-they-be-used","status":"publish","type":"post","link":"https:\/\/www.deltics.co.nz\/blog\/posts\/48\/","title":{"rendered":"Anonymous Methods &#8211; When Should They Be Used?"},"content":{"rendered":"<span class=\"rt-reading-time\" style=\"display: block;\"><span class=\"rt-label rt-prefix\">[Estimated Reading Time: <\/span> <span class=\"rt-time\">5<\/span> <span class=\"rt-label rt-postfix\">minutes]<\/span><\/span><p>Anonymous methods are generating a lot of buzz in the Delphi community right now, being one of the bigger changes heading our way in the forthcoming Tiburon (Delphi 2009), along with Unicode and Generics.<\/p>\n<p>Unlike Unicode and Generics however, the usefulness of anonymous methods is not nearly as clear.<\/p>\n<p><!--more--><\/p>\n<h3>On Joel On Software<\/h3>\n<p><a href=\"http:\/\/www.joelonsoftware.com\/items\/2006\/08\/01.html\">Joel On Software<\/a> has been invoked as an authority.\u00a0 Unfortunately, as Joel himself has previously admitted, he does not actually use Delphi, and a great deal of the usefulness he sees in anonymous methods seems to stem from this fact, in that what he describes as the principal benefits of anonymous methods has always been achievable in Delphi.<\/p>\n<p>To paraphrase his material on this point:<\/p>\n<pre class=\"delphi\">    procedure Cook(const aIngredient1, aIngredient2: String;\r\n                   const aCookingMethod: TCookingMethod);\r\n    begin\r\n      Alert('get the ' + aIngredient);\r\n      aCookingMethod(aIngredient1);\r\n      aCookingMethod(aIngredient2);\r\n    end;\r\n\r\nCook( 'lobster', 'water',   PutInPot );\r\nCook( 'chicken', 'coconut', BoomBoom );<\/pre>\n<p><strong>Joel asks: <\/strong><em> Can your language do this?<\/em><\/p>\n<p>If the language is Delphi, yes.\u00a0 We don&#8217;t need anonymous methods for this.<\/p>\n<p>But that is not the only use for anonymous methods espoused by Joel.\u00a0 He goes on to talk briefly about threading, before seeming to me to go off at something of a tangent to talk about <a href=\"http:\/\/en.wikipedia.org\/wiki\/MapReduce\">MapReduce<\/a>, where the applicability of anonymous methods is a little hard to fathom (in the context of languages that &#8220;<em>can<\/em> do this&#8221;) and I&#8217;m certain that the <a href=\"http:\/\/labs.google.com\/papers\/mapreduce.html\">actual Google MapReduce implementation<\/a> is a great deal more complex than Joel&#8217;s summary, but I&#8217;m not so sure that anonymous methods were critical to it&#8217;s success, rather than just happening to be a part of it.<\/p>\n<p>One wonders if they would have featured at all if Google had used Delphi.\u00a0 \ud83d\ude42<\/p>\n<h3>Anonymous Methods and Threading<\/h3>\n<p>In a different blog, <a href=\"http:\/\/delphi.fosdal.com\/2008\/08\/anonymous-methods-when-to-use-them.html\">Lars Fosdal<\/a> also mentions threading.<\/p>\n<p>Coming at the subject with the Delphi perspective that Joel does not have, Lars aligns the benefits of anonymous methods against the failings of TThread.\u00a0 Not unreasonable, given that TThread is the &#8220;out of the box&#8221; approach to threading in Delphi and it undeniably has a number of shortcomings.\u00a0 But TThread is not the only game in town for Delphi developers.\u00a0 I myself have needed a more lightweight approach to threading in the past.\u00a0 So I made one.\u00a0 I called it TMotile (<a href=\"http:\/\/en.wikipedia.org\/wiki\/Commonwealth_Saga\">a work by Peter F Hamilton<\/a> brought the term <a href=\"http:\/\/www.answers.com\/topic\/motility\">motile<\/a> to my attention, and the fit was obvious in my mind).<\/p>\n<p>My TMotile class can be used in two ways.\u00a0 First to execute some procedure in a fire-and-forget background thread:<\/p>\n<pre class=\"delphi\">    procedure SomeProcedure;\r\n    begin\r\n      \/\/ ...\r\n    end;\r\n\r\nTMotile.Execute( SomeProcedure );<\/pre>\n<p>Or secondly in a way perhaps more familiar to those already used to TThread:<\/p>\n<pre class=\"delphi\">    TMyMotile = class( TMotile )\r\n    protected\r\n      procedure Execute; override;\r\n    end;\r\n\r\n    procedure TMyMotile.Execute;\r\n    begin\r\n      \/\/ ...\r\n    end;\r\n\r\nTMyMotile.Create;<\/pre>\n<p>With anonymous methods that fire-and-forget usage could be made simpler:<\/p>\n<pre class=\"delphi\">TMotile.Execute( procedure\r\n                 begin\r\n                   \/\/ ...\r\n                 end; );<\/pre>\n<p>Of course, that &#8220;simpler&#8221; observation is, I think, debatable.\u00a0 If it is &#8220;simpler&#8221; at all, then actually it isn&#8217;t by very much, and arguably it introduces an unacceptable level of noise into the code.\u00a0 This doesn&#8217;t appear to be the case when viewed in isolation, but in the context of a longer sequence of code where only one statement is invoked to create a thread to handle background execution of some other code, seeing the body of that background code <span style=\"text-decoration: underline;\">is<\/span> &#8220;noise&#8221;.<\/p>\n<p>There is an even greater advantage when the body of the anonymous procedure captures state from the context in which it is created.\u00a0 In those situations then this usage simply cannot work without anonymous methods, requiring a subclass of TMotile (or TThread) in order to explicitly capture that state from the context and make it available to the threaded procedure:<\/p>\n<pre class=\"delphi\">    TMyMotile = class(TMotile)\r\n    private\r\n      fContextVar: ...;\r\n    protected\r\n      procedure Execute;\r\n    public\r\n      property ContextVar: .. write fContextVar;\r\n    end;\r\n\r\n    procedure TMyMotile.Execute;\r\n    begin\r\n      ..  fContextVar  ..;\r\n    end;\r\n\r\nmm := TMyMotile.Create;\r\nmm.ContextVar1 := SomeContextValue;\r\nmm.Execute;<\/pre>\n<p>Which can be replaced with:<\/p>\n<pre class=\"delphi\">mm := TMotile.Execute( procedure;\r\n                       begin\r\n                         .. SomeContextValue ..;\r\n                       end; );<\/pre>\n<p>Which is undeniably neat. Both in the sense that is it clever and a great deal more concise.\u00a0 But I am still not convinced that this convenience is worth getting all that excited about &#8211; It has not enabled anything that was previously impossible, nor even especially difficult either to implement or to understand, and that noise is still there.<\/p>\n<p>Indeed, anonymous methods do not even eradicate the infrastructure that is required to support it, they just hide it.<\/p>\n<p>If it&#8217;s hidden, I can&#8217;t fix it or improve it or adapt it to better suit a specific use.\u00a0 If it&#8217;s hidden I may never the less need to take it into account to understand what unfamiliar code does and how &#8211; hiding it just makes it that much harder to identify and requires me to bring that knowledge of the hidden details with me.<\/p>\n<p>For one thing of course, if this threaded code should later evolve and require some mechanism to pass information <span style=\"text-decoration: underline;\">back<\/span> to the context that originated it &#8211; or some other context &#8211; having that threaded code represented by an identified and referencable object provides exactly the mechanism we need.\u00a0 Without any such visible device, yet more wizardry is needed to provide that mechanism without resorting to simply exposing and extending the pretty basic infrastructure.<\/p>\n<h3>With Great Anonymity Comes Great Responsibility<\/h3>\n<p>Having anonymous methods in the language does not compel us to use them, and unlike Generics or even Unicode to an extent, using them in your code will not compel <span style=\"text-decoration: underline;\">others<\/span> to use them either, if they do not wish to.\u00a0 So what&#8217;s the harm?<\/p>\n<p>Well, of course, the same could be said of <strong>with<\/strong> &#8211; and indeed, the similarity is quite striking.\u00a0 Both provide a means of hiding an implementation detail and avoiding the onerous task of encumbering that detail with an identity.\u00a0 <strong>with<\/strong> is, somewhat famously, regarded with disdain for the way that this hiding of details introduces problems.\u00a0 Not least when debugging (and the prospect of debugging anonymous methods is similarly intriguing, to say the least).<\/p>\n<p>So if we all only use anonymous methods responsibly, we&#8217;ll be fine.<\/p>\n<p>Which call to mind Eddie Izzard&#8217;s response to the NRA&#8217;s assertion that &#8220;Guns don&#8217;t kill people, people kill people&#8221; &#8230;..<\/p>\n<p><em>&#8230;and monkeys do too (if they have a gun)<\/em><\/p>\n<p>Speaking of Eddie Izzard, if you haven&#8217;t heard his Death Star Canteen sketch, then allow YouTube to introduce you to in <a href=\"http:\/\/www.youtube.com\/watch?v=Sv5iEK-IEzw\">glorious LegoVision<\/a>.<\/p>\n<p>Any excuse.\u00a0 \ud83d\ude42<\/p>\n<h3>Other Parallels<\/h3>\n<p>No not a further examination of threading, but the use of one thing to draw a parallel, or a comparison, with something else.\u00a0 In this case, let us imagine we are putting together a web site, and on some of our pages we have some content that isn&#8217;t directly relevant to the page it is on.\u00a0 Content that certainly doesn&#8217;t have to be read at the time, but which perhaps isn&#8217;t likely ever to be read alone.\u00a0 It&#8217;s not going to appear in our site navigation or even the table of contents necessarily.<\/p>\n<p>It&#8217;s content, but it doesn&#8217;t have an absolute identity outside of some other context in which it is referenced.\u00a0 On the printed page, it would be a footnote or an entry in the bibliography.<\/p>\n<p>These things to a written language are, essentially, what anonymous methods are to our code.<\/p>\n<p>So why do we have footnotes?\u00a0 Why do we use links in web pages, instead of just quoting, verbatim and inline, the content we would like the reader to perhaps come back to later, and just require them to skip over it in the meantime.<\/p>\n<p>The question is of course rhetorical.<\/p>\n<p>This is essentially what anonymous methods will bring to your source code.<\/p>\n<p>I may never write code this way myself, but I am not looking forward to the first time I have to read someone else&#8217;s code written that way.<\/p>\n<h3>So, When Should They Be Used?<\/h3>\n<p>The title of this post posed a question, and it&#8217;s only fair that I answer it.<\/p>\n<p>As things stand, I would have to say that anonymous methods should be used <em>only<\/em> when you absolutely have to, and so far I have not yet seen an example where anonymous methods are the only way to achieve anything.<\/p>\n<p>I may yet change my mind, and more examples have been promised by CodeGear.\u00a0 But CodeGear didn&#8217;t invent these things, and they aren&#8217;t new, as plenty of people point out &#8211; compelling and obvious examples should already be readily available, albeit not in Delphi.<\/p>\n<p>Where are they?<\/p>\n","protected":false},"excerpt":{"rendered":"<p><span class=\"rt-reading-time\" style=\"display: block;\"><span class=\"rt-label rt-prefix\">[Estimated Reading Time: <\/span> <span class=\"rt-time\">5<\/span> <span class=\"rt-label rt-postfix\">minutes]<\/span><\/span> Explores the relevance of authorities supposed to be making a good case for anonymous methods<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"jetpack_publicize_message":"","jetpack_is_tweetstorm":false,"jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":[]},"categories":[4,7],"tags":[15,292,13,16,293,17],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/p1TKYv-M","jetpack_sharing_enabled":true,"jetpack-related-posts":[{"id":28,"url":"https:\/\/www.deltics.co.nz\/blog\/posts\/28\/","url_meta":{"origin":48,"position":0},"title":"Tiburon Preview","date":"02 Aug 2008","format":false,"excerpt":"A roundup of that part of the Preview I saw of Tiburon - the next release of Delphi from CodeGear.","rel":"","context":"In &quot;Delphi&quot;","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":338,"url":"https:\/\/www.deltics.co.nz\/blog\/posts\/338\/","url_meta":{"origin":48,"position":1},"title":"Delphi 2009 &#8211; A Heads-Up for Low-Level Coders","date":"13 Sep 2008","format":false,"excerpt":"Prompted by a conversation with some colleagues where-in we collectively speculated about the implementation details of a generic class and what impact - if any - this might have on performance vs a \"traditional\" polymorphic equivalent, I threw together a quick performance test case in my Smoketest framework, and as\u2026","rel":"","context":"In &quot;Delphi&quot;","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":706,"url":"https:\/\/www.deltics.co.nz\/blog\/posts\/706\/","url_meta":{"origin":48,"position":2},"title":"Making a case for Strings, the sane way","date":"02 Dec 2010","format":false,"excerpt":"Lars Fosdal responded to my previous post suggesting a way of implementing string support in a case-like construct (but not actually a case statement) using generics and anonymous methods. All very clever, but way, way too complicated and - if you don't mind me saying so - as ugly as\u2026","rel":"","context":"In &quot;Delphi&quot;","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":180,"url":"https:\/\/www.deltics.co.nz\/blog\/posts\/180\/","url_meta":{"origin":48,"position":3},"title":"Latest Tibur\u00f3n Preview","date":"14 Aug 2008","format":false,"excerpt":"I was a little disappointed that the preview webinar this morning was little more than a re-run of the same content from a little over a week ago, albeit with some downloadable PowerPoint slides this time. It was at least an opportunity for some more Q&A and a couple of\u2026","rel":"","context":"In &quot;Delphi&quot;","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":244,"url":"https:\/\/www.deltics.co.nz\/blog\/posts\/244\/","url_meta":{"origin":48,"position":4},"title":"Generic Methods and Type Inferencing","date":"25 Aug 2008","format":false,"excerpt":"In the new Delphi forums recently, Barry Kelly responded to a question about lambda expression syntax in Tibur\u00f3n with this observation: This syntax needs type inference. Our compiler was not originally written to support type inference, but work to support type inference is orthogonal to supporting anonymous methods. ...\u00a0 you'll\u2026","rel":"","context":"In &quot;Delphi&quot;","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":2006,"url":"https:\/\/www.deltics.co.nz\/blog\/posts\/2006\/","url_meta":{"origin":48,"position":5},"title":"Blowing Smoke&#8230;","date":"01 Nov 2013","format":false,"excerpt":"To alleviate the grind of polishing and sanitising my code (and, let's be honest, just plain 'fixing' it in some cases) ready for release, I have re-kindled my participation on Stack Overflow. In a happy confluence yesterday a question came up which allowed me to exercise one of the libraries\u2026","rel":"","context":"In &quot;Delphi&quot;","img":{"alt_text":"Ready to Run","src":"https:\/\/i0.wp.com\/www.deltics.co.nz\/blog\/wp-content\/uploads\/Screen-Shot-2013-11-01-at-09.00.33.png?resize=350%2C200&ssl=1","width":350,"height":200},"classes":[]}],"_links":{"self":[{"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/posts\/48"}],"collection":[{"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/comments?post=48"}],"version-history":[{"count":18,"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/posts\/48\/revisions"}],"predecessor-version":[{"id":463,"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/posts\/48\/revisions\/463"}],"wp:attachment":[{"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/media?parent=48"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/categories?post=48"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/tags?post=48"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}