{"id":412,"date":"2008-10-01T17:34:49","date_gmt":"2008-10-01T05:34:49","guid":{"rendered":"https:\/\/www.deltics.co.nz\/blog\/?p=412"},"modified":"2008-10-01T17:34:49","modified_gmt":"2008-10-01T05:34:49","slug":"proposal-for-automated-variables","status":"publish","type":"post","link":"https:\/\/www.deltics.co.nz\/blog\/posts\/412\/","title":{"rendered":"Proposal for Automated Variables"},"content":{"rendered":"<span class=\"span-reading-time rt-reading-time\" style=\"display: block;\"><span class=\"rt-label rt-prefix\">[Estimated Reading Time: <\/span> <span class=\"rt-time\"> 4<\/span> <span class=\"rt-label rt-postfix\">minutes]<\/span><\/span><p><em><strong>Or: <\/strong>&#8220;Environmentally Friendly Coding &#8211; Recycle Your Keywords<\/em>&#8221;<\/p>\n<p>Yesterday I logged a Quality Central report proposing the addition of support for &#8220;automatic variables&#8221; to the Delphi language.\u00a0 Not only is it an <span style=\"text-decoration: underline;\">excellent<\/span> idea (in my humble and utterly objective opinion :)), but there is already a keyword in the language that could be co-opted for this purpose, a keyword that has been at something of a loose-end since it was deprecated (rendered obsolete even) a long, long time ago&#8230;<\/p>\n<p><!--more--><\/p>\n<p>The language keyword in question is <strong>automated<\/strong>.\u00a0 This was introduced in Delphi 2.0 as part of the initial implementation to support COM automation and, if memory serves, deprecated in the very next release when &#8220;proper&#8221; (albeit COM) interfaces were added to the language.<\/p>\n<p>The functionality that <strong>AutoFree()<\/strong> provides is similar to the concept of an <a href=\"http:\/\/en.wikipedia.org\/wiki\/Auto_ptr\" target=\"_blank\">auto pointer<\/a> &#8211; a specific variant of the general concept of a <a href=\"http:\/\/en.wikipedia.org\/wiki\/Smart_pointer\" target=\"_blank\">smart pointer<\/a>.\u00a0 &#8220;auto&#8221;&#8230; &#8220;automatic&#8221;&#8230; &#8220;automated&#8221;&#8230; the similarity in the terms, and the relevance of the semantics, is striking.\u00a0 To me at least.<\/p>\n<p>The proposal in Quality Central drew inspiration directly from exchanges in the comments on my post on an <strong>AutoFree()<\/strong> implementation and a realisation that the required behaviour is very similar to that already implemented for interface references &#8211; it would not be entirely alien to the Delphi language.<\/p>\n<p>Indeed I believe it would be quite easily understood and welcomed by most, if not all, developers.<\/p>\n<h2>The Proposal<\/h2>\n<p>The <strong>automated<\/strong> keyword should be supported as a decoration on variable declarations.\u00a0 That is local variables, member variables and unit variables:<\/p>\n<pre class=\"delphi\">interface\r\n\r\n  type\r\n    TFoo = class\r\n    private\r\n      fBar: TBar automated;\r\n    end;\r\n\r\nimplementation\r\n\r\n  var\r\n    _Bar: TBar automated;\r\n\r\n  function FooFn;\r\n  var\r\n    bar: TBar automated;\r\n  begin\r\n    :\r\n  end;<\/pre>\n<p>The rules for the keyword and the effect of it shall be as follows:<\/p>\n<p style=\"padding-left: 30px;\">&#8211; The <strong>automated<\/strong> keyword shall be valid only for pointer and object reference type variables. <strong>(*)<\/strong><\/p>\n<p style=\"padding-left: 30px;\">&#8211; When marked as <strong>automated<\/strong> the compiler shall emit code to initialize a variable to <strong>NIL<\/strong>. <em>This already occurs for local variables of certain types, most notably interface references, as well as all member variables <\/em><em>(albeit indirectly in that case)<\/em><em>, and currently has to be specified directly, if required, for unit variables.<\/em><\/p>\n<p style=\"padding-left: 30px;\">&#8211; When marked as <strong>automated<\/strong> the compiler shall emit code to finalize a variable in a manner appropriate to it&#8217;s type.\u00a0 For object references this shall be a call to <strong>Free<\/strong>; for pointers a call to <strong>FreeMem()<\/strong>.\u00a0 <em>This is directly equivalent to the code already emitted by the compiler to finalize interface references by calling <strong>Release()<\/strong>.<\/em><\/p>\n<p style=\"padding-left: 30px;\">&#8211; <strong>automated<\/strong> would <span style=\"text-decoration: underline;\">not<\/span> be combinable with <strong>absolute<\/strong>.<\/p>\n<p><em><strong>(*)<\/strong> &#8211; it could also be supported on record types with the proviso that the record type in question supports a parameterless <strong>constructor<\/strong> (to be called to initialize the record) and a lone <strong>destructor<\/strong> (called to finalize the record).\u00a0 But to keep things simple lets stick to object references and pointers, for now at least.<br \/>\n<\/em><\/p>\n<p>The effect on code of the use of this keyword would be to facilitate:<\/p>\n<p style=\"padding-left: 30px;\">1. resource protection for temporary objects held in local variables without the need for <strong>try..finally<\/strong> blocks.<\/p>\n<p style=\"padding-left: 30px;\">2. reliable clean up of dependent objects in object hierarchies without the need for objects to implement a <strong>destructor<\/strong> (solely) to free those dependent objects.\u00a0 Destructors may still be necessary for other purposes of course.<\/p>\n<p style=\"padding-left: 30px;\">3. reliable clean up of unit (a.k.a &#8220;global&#8221;) objects without the need for a unit <strong>finalization<\/strong>.\u00a0 Again, finalization may still be required for other purposes.<\/p>\n<p>Note however that it would not prevent these existing techniques from functioning, if required or preferred.<\/p>\n<p>There is only one possible danger that I foresee, which is that a developer might mark a variable as automated but then dispose of the referenced object\/memory explicitly without re-initializing the variable.\u00a0 e.g.:<\/p>\n<pre class=\"delphi\">  procedure SomeFn;\r\n  var\r\n    bar: TBar automated;\r\n  begin\r\n    bar := TBar.Create;\r\n    bar.Free;\r\n  end;<\/pre>\n<p>In this case, when <strong>SomeFn<\/strong> exits, the finalization of <strong>bar<\/strong> will likely result in an error since <strong>bar<\/strong> has been left holding a reference to an object that has already been <strong>Free<\/strong>&#8216;d.<\/p>\n<p>Note that the initialization of <strong>bar<\/strong> as NIL (as a consequence of being <strong>automated<\/strong>) specifically avoids any problem if bar is only assigned a reference conditionally in the code.<\/p>\n<p>Note also that explicitly disposing an automated variable is not in and of itself problematic, as long as the variable is also then explicitly re-set to <strong>NIL<\/strong>.\u00a0 In the above example, if bar had been <strong>NIL<\/strong>&#8216;d once freed, or <strong>FreeAndNIL()<\/strong> had been used, then there would not be any problem with the automated behaviour of <strong>bar<\/strong>.<\/p>\n<p>The code below illustrates safe explicit disposal and potentially conditional assignment of an automated reference:<\/p>\n<pre class=\"delphi\">  procedure SomeFn;\r\n  var\r\n    bar: TBar automated;\r\n  begin\r\n    bar := TBar.Create;\r\n\r\n    \/\/ do some work with \"bar\"\r\n\r\n    FreeAndNIL(bar);\r\n\r\n    if SomeCondition then\r\n    begin\r\n      bar := TBar.Create;\r\n      \/\/ do more work with a new \"bar\"\r\n    end;\r\n  end;<\/pre>\n<p>This code is perfectly safe, will not result in a runtime error and will not leak a <strong>TBar<\/strong>.<\/p>\n<p>The potential dangers and pitfalls of an automated variable behaviour implemented as described are actually no different to the potential dangers and pitfalls associated with the manual techniques that it could replace.<\/p>\n<p>I should also mention that I cannot see that the proposal described here would necessarily interfere with, or be interfered with by, the existing, deprecated usage of the <strong>automated<\/strong> keyword.<\/p>\n<p>A final observation is that this implementation &#8220;feels very Pascal&#8217;ly&#8221; to me.\u00a0 In a <span style=\"text-decoration: underline;\">good<\/span> way.<\/p>\n<h2>Call To Action<\/h2>\n<p>The <a href=\"http:\/\/qc.codegear.com\/wc\/qcmain.aspx?d=67324\" target=\"_blank\">Quality Central report # is 67324<\/a>.<\/p>\n<p>If you feel the idea has merit please vote for it.<\/p>\n<p>If you feel it needs refining, comment on it (in QC, rather than here).<\/p>\n","protected":false},"excerpt":{"rendered":"<p><span class=\"span-reading-time rt-reading-time\" style=\"display: block;\"><span class=\"rt-label rt-prefix\">[Estimated Reading Time: <\/span> <span class=\"rt-time\"> 4<\/span> <span class=\"rt-label rt-postfix\">minutes]<\/span><\/span>Or: &#8220;Environmentally Friendly Coding &#8211; Recycle Your Keywords&#8221; Yesterday I logged a Quality Central report proposing the addition of support for &#8220;automatic variables&#8221; to the Delphi language.\u00a0 Not only is it an excellent idea (in my humble and utterly objective opinion :)), but there is already a keyword in the language that could be co-opted [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_feature_clip_id":0,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2},"jetpack_post_was_ever_published":false},"categories":[4],"tags":[292,68],"class_list":["post-412","post","type-post","status-publish","format-standard","hentry","category-delphi","tag-delphi","tag-smart-pointers"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/p1TKYv-6E","jetpack_sharing_enabled":true,"jetpack-related-posts":[],"_links":{"self":[{"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/posts\/412","targetHints":{"allow":["GET"]}}],"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=412"}],"version-history":[{"count":5,"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/posts\/412\/revisions"}],"predecessor-version":[{"id":417,"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/posts\/412\/revisions\/417"}],"wp:attachment":[{"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/media?parent=412"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/categories?post=412"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/tags?post=412"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}