{"id":700,"date":"2010-11-30T19:38:01","date_gmt":"2010-11-30T07:38:01","guid":{"rendered":"https:\/\/www.deltics.co.nz\/blog\/?p=700"},"modified":"2010-11-30T20:26:00","modified_gmt":"2010-11-30T08:26:00","slug":"the-case-for-case","status":"publish","type":"post","link":"https:\/\/www.deltics.co.nz\/blog\/posts\/700\/","title":{"rendered":"The case for case[]"},"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\"> 3<\/span> <span class=\"rt-label rt-postfix\">minutes]<\/span><\/span><p>Eric Grange (resurrector of the increasingly interesting looking DWS project) recently posted about <a href=\"http:\/\/delphitools.info\/2010\/11\/29\/iif-anonymous-expression-parameters\/\">a new idea he has had for the DWS engine<\/a>, which in turn gave me an idea, or rather, prompted me to come up with what I think may be a new spin on an old one.<br \/>\n<!--more--><br \/>\nI briefly posted my idea to the comments on his post, and for more details of his suggestion please visit his pages.  Here I shall spend more time outlining my idea, inspired by, but not necessarily directly connected to his.<\/p>\n<p>The old problem at the heart of the idea, is the lack of &#8220;iif()&#8221; or so called &#8220;ternary operator&#8221; in Delphi.<\/p>\n<p>We do have <strong>IfThen()<\/strong> in limited forms in various places in the RTL:<\/p>\n<pre class=\"brush: delphi; title: ; notranslate\" title=\"\">\r\n   s := IfThen(SomeCondition, stringA, stringB);\r\n<\/pre>\n<p>Which provides a neat (i.e. condensed) alternative to:<\/p>\n<pre class=\"brush: delphi; title: ; notranslate\" title=\"\">\r\n  if SomeCondition then\r\n    s := stringA\r\n  else\r\n    s := stringB;\r\n<\/pre>\n<p>Except it doesn&#8217;t quite do that, as anyone who has encountered this function will testify.<\/p>\n<p>Problems from the fact that <strong>IfThen()<\/strong> is just a function, like every other function in Delphi, and to pass expressions as parameters to that function, those parameter expression must be first evaluated.  A simple way to demonstrate the problem is to (try to) use <strong>IfThen()<\/strong> to retrieve a property of an object or yield a default if the object is not assigned:<\/p>\n<pre class=\"brush: delphi; title: ; notranslate\" title=\"\">\r\n   s := IfThen(Assigned(obj), obj.Name, '(no object assigned)');\r\n<\/pre>\n<p>Because the parameters to the <strong>IfThen()<\/strong> function must be evaluated before <strong>IfThen()<\/strong> can itself be called, the <strong>obj.Name<\/strong> reference will cause an access violation if <strong>obj<\/strong> is not assigned, precisely what we were trying to avoid!<\/p>\n<p><a href=\"http:\/\/delphitools.info\/2010\/11\/29\/iif-anonymous-expression-parameters\/\">Eric&#8217;s idea was to support a way of declaring parameters<\/a> that indicate that if those parameters represent an expression, that the expression itself in effect be passed and only evaluated within the function if required.<\/p>\n<p>I can see how this is easily possible in a scripting engine such as DWS, and I can even see how it might be achieved with anonymous methods in Delphi, except that I really wouldn&#8217;t want to see that any more than I would be happy to see a generalised <strong>IfThen()<\/strong> contrived using generics, which would look something like:<\/p>\n<pre class=\"brush: delphi; title: ; notranslate\" title=\"\">\r\n   TTernary&lt;T&gt; = class\r\n      class function IfThen(aCondition: Boolean; aTrueResult, aFalseResult: T): T;\r\n   end;\r\n\r\n   \/\/ In usage:\r\n   s := TTernary&lt;String&gt;.IfThen( condition, stringA, stringB );\r\n<\/pre>\n<p>Some might call me &#8220;old fashioned&#8221; for not welcoming such new syntax.<\/p>\n<p>I don&#8217;t think it has anything to do with being &#8220;old fashioned&#8221;, unless it is old fashioned to find such syntax ugly, cumbersome and just plain hard to read (not hard to understand, but physically hard read &#8211; it being full of syntax and punctuation, far more than should be required).<\/p>\n<p>Not to mention the flat out ridiculous need to place the function in an extraneous class, just to gain access to generics support.<\/p>\n<p>But I digress.<\/p>\n<p>My idea came from thinking about what the code that the operator itself represents (and possibly even generates).  To recap:<\/p>\n<pre class=\"brush: delphi; title: ; notranslate\" title=\"\">\r\n   s := IfThen(SomeCondition, stringA, stringB);\r\n<\/pre>\n<p>Is equivalent to:<\/p>\n<pre class=\"brush: delphi; title: ; notranslate\" title=\"\">\r\n  if SomeCondition then\r\n    s := stringA\r\n  else\r\n    s := stringB;\r\n<\/pre>\n<p>Which in turn is equivalent to:<\/p>\n<pre class=\"brush: delphi; title: ; notranslate\" title=\"\">\r\n  case SomeCondition of\r\n    TRUE  : s := stringA\r\n    FALSE : s := stringB;\r\n  end;\r\n<\/pre>\n<p>Now it seems quite clear and obvious to me that this form of the code quickly identifies how much of the code is not just boilerplate, but merely syntactic scaffolding, and could be replaced by&#8230; (drum roll please&#8230;)<\/p>\n<pre class=\"brush: delphi; title: ; notranslate\" title=\"\">\r\n  s := case&#x5B;SomeCondition, stringA, stringB];\r\n<\/pre>\n<p>Or some variation on this.  I suggest re-using the keyword &#8220;case&#8221; &#8211; perfectly valid since it is being used in exactly the same way as it&#8217;s current use, merely employing a slightly different syntax.<\/p>\n<p>Similarly, using <strong>[]<\/strong> (rather than <strong>()<\/strong>) ensures that the new syntax itself is not confusable with that syntax for case that is already supported and also differentiates this syntax from a function call which it might otherwise appear to resemble.<\/p>\n<p>TA-DA!<\/p>\n<p>I don&#8217;t know about you, but I would love to see this added to the language, and when I get my hands on DWS (and some time) I hope to explore adding it to at least that scripting version of Pascal.<\/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\"> 3<\/span> <span class=\"rt-label rt-postfix\">minutes]<\/span><\/span>Eric Grange (resurrector of the increasingly interesting looking DWS project) recently posted about a new idea he has had for the DWS engine, which in turn gave me an idea, or rather, prompted me to come up with what I think may be a new spin on an old one.<\/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":[125,292,13,127,126],"class_list":["post-700","post","type-post","status-publish","format-standard","hentry","category-delphi","tag-case","tag-delphi","tag-language","tag-object-pascal","tag-ternary-operator"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/p1TKYv-bi","jetpack_sharing_enabled":true,"jetpack-related-posts":[],"_links":{"self":[{"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/posts\/700","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=700"}],"version-history":[{"count":5,"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/posts\/700\/revisions"}],"predecessor-version":[{"id":705,"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/posts\/700\/revisions\/705"}],"wp:attachment":[{"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/media?parent=700"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/categories?post=700"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/tags?post=700"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}