{"id":2624,"date":"2017-04-25T12:25:06","date_gmt":"2017-04-25T00:25:06","guid":{"rendered":"https:\/\/www.deltics.co.nz\/blog\/?p=2624"},"modified":"2017-04-25T15:19:39","modified_gmt":"2017-04-25T03:19:39","slug":"expressive-if-and-case","status":"publish","type":"post","link":"https:\/\/www.deltics.co.nz\/blog\/posts\/2624\/","title":{"rendered":"Expressive If and Case &#8230;"},"content":{"rendered":"<span class=\"rt-reading-time\" style=\"display: block;\"><span class=\"rt-label rt-prefix\">[Estimated Reading Time: <\/span> <span class=\"rt-time\">2<\/span> <span class=\"rt-label rt-postfix\">minutes]<\/span><\/span><p>A quick post on a small but hugely useful little language feature in Oxygene&#8230; <strong>if<\/strong> expressions.<\/p>\n<p><!--more--><\/p>\n<p>Many people will be familiar with the so-called <em><a href=\"https:\/\/en.wikipedia.org\/wiki\/%3F:\">ternary operator<\/a><\/em>.  Delphi developers will also be aware that there is no direct equivalent in Delphi.<\/p>\n<p>In &#8216;C&#8217; and other languages we can write a statement such as this:<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\n    x = a ? b : c;\r\n<\/pre>\n<p>The result is that <strong>x<\/strong> is assigned the value of <strong>b<\/strong> when <strong>a<\/strong> is <em>true<\/em>, otherwise <strong>x<\/strong> is assigned the value of <strong>c<\/strong>.<\/p>\n<p>The ternary operator evaluates only either <strong>b<\/strong> or <strong>c<\/strong> as determined by the condition <strong>a<\/strong>.<\/p>\n<p>In Delphi you can use the <strong>IfThen()<\/strong> function (for supported types of values of <strong>b<\/strong> and <strong>c<\/strong>) but this is notorious for the short-coming that regardless of the value of condition <strong>a<\/strong> both <strong>b<\/strong> and <strong>c<\/strong> will be evaluated.<\/p>\n<p>At best this makes <strong>IfThen()<\/strong> potentially less efficient and at worst it can render it entirely useless if the evaluation of <strong>b<\/strong> or <strong>c<\/strong> has undesirable consequences or side-effects.<\/p>\n<p>For example if you tried to use <strong>IfThen()<\/strong> to avoid a division by zero:<\/p>\n<pre class=\"brush: delphi; title: ; notranslate\" title=\"\">\r\n     x := IfThen( divisor &lt;&gt; 0, numerator div divisor, 0);\r\n<\/pre>\n<p>This code will still throw a division by zero exception when <strong>divisor<\/strong> = zero.  The equivalent ternary expression would not:<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\n     x = divisor != 0 ? numerator \/ divisor : 0;\r\n<\/pre>\n<p>In Delphi therefore you have no choice in these situations but to long-hand an <strong>if-else<\/strong> statement:<\/p>\n<pre class=\"brush: delphi; title: ; notranslate\" title=\"\">\r\n   if divisor &lt;&gt; 0 then\r\n     x := numerator div divisor\r\n   else\r\n     x := 0;\r\n<\/pre>\n<p>In Delphi therefore it is not uncommon to find this one, simple problem solved by at least three different techniques:<\/p>\n<pre class=\"brush: delphi; title: ; notranslate\" title=\"\">\r\n    \/\/ 1. Where the values of b and c are supported by IfThen\r\n    \/\/     and have no side effects:\r\n\r\n    x := IfThen( a, b, c );\r\n\r\n\r\n    \/\/ 2. Where b and\/or c are variable expressions that \r\n    \/\/     do or may have side-effects:\r\n\r\n    if a then\r\n      x := b\r\n    else\r\n      x := c;\r\n\r\n\r\n    \/\/ 3. Where the values of b and c are constant expressions:\r\n\r\n    const\r\n      AVALUE: array[false..true] of Integer = (0, 42);\r\n\r\n    x := AVALUE[a];\r\n\r\n<\/pre>\n<p>Oxygene addresses this gap by simply re-purposing the <strong>if<\/strong> statement as an expression:<\/p>\n<pre class=\"brush: oxygene; title: ; notranslate\" title=\"\">\r\n  x := if divisor &lt;&gt; 0 then numerator div divisor else 0;\r\n<\/pre>\n<p>But Oxygene also goes further, extending the same behaviour to <strong>case<\/strong> statements, for example:<\/p>\n<pre class=\"brush: oxygene; title: ; notranslate\" title=\"\">\r\n   x := case selector of\r\n     CONST_A : valueA;\r\n     CONST_B : valueB;\r\n     CONST_C : valueC;\r\n   end;\r\n<\/pre>\n<p>Applying <strong>case<\/strong> and <strong>if<\/strong> in this way eliminates the duplication of the assignment expression in the overall statement and can be applied consistently in other scenarios such as choosing values to pass as parameters to functions:<\/p>\n<pre class=\"brush: oxygene; title: ; notranslate\" title=\"\">\r\n   Foo( a, if a &gt; 42 then b else c );\r\n<\/pre>\n<p>The result is code that is consistent as well as both (imho) more concise and also clearer in intent than an <strong>if-else<\/strong> or (for <em>case<\/em>) a series of <strong>if-else if-else if<\/strong> statements.<\/p>\n<p>Although a seemingly very small thing it is one of my favorite features of the Oxygene implementation of Object Pascal.<\/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\">2<\/span> <span class=\"rt-label rt-postfix\">minutes]<\/span><\/span> A quick post on a small but hugely useful little language feature in Oxygene&#8230; if expressions.<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","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":true,"jetpack_social_options":[]},"categories":[4],"tags":[125,320,13,127,181],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/p1TKYv-Gk","jetpack_sharing_enabled":true,"jetpack-related-posts":[{"id":700,"url":"https:\/\/www.deltics.co.nz\/blog\/posts\/700\/","url_meta":{"origin":2624,"position":0},"title":"The case for case[]","date":"30 Nov 2010","format":false,"excerpt":"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.\u2026","rel":"","context":"In &quot;Delphi&quot;","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":2597,"url":"https:\/\/www.deltics.co.nz\/blog\/posts\/2597\/","url_meta":{"origin":2624,"position":1},"title":"(True = 1) and (True = &#8216;-1&#8217;) ?","date":"17 Mar 2017","format":false,"excerpt":"It has been observed that the Delphi documentation states that the constants True and False have the values 1 and 0 respectively, not the -1 and 0 that the default string conversions apply. This does actually make sense but also lays a trap for the unwary. True, True, Wherefore Art\u2026","rel":"","context":"In &quot;Delphi&quot;","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":2265,"url":"https:\/\/www.deltics.co.nz\/blog\/posts\/2265\/","url_meta":{"origin":2624,"position":2},"title":"Nullable Types.  Not!","date":"23 Aug 2014","format":false,"excerpt":"I recently mentioned that RemObjects have placed their OS X native IDE - a.k.a. Fire - into public beta. I haven't been using it myself (yet) but have been following developments in the RemObjects Talk forums with interest, and a new feature in the Elements 8.0 compiler (also part of\u2026","rel":"","context":"In &quot;Delphi&quot;","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":1882,"url":"https:\/\/www.deltics.co.nz\/blog\/posts\/1882\/","url_meta":{"origin":2624,"position":3},"title":"Not Your Grand-Daddy&#8217;s Pascal (or Java)","date":"15 Oct 2013","format":false,"excerpt":"I've mentioned some of the cool stuff in the Oxygene language in various posts and thought it would be a good idea to list them again, along with some others that I've not previously mentioned. Oxygene Everywhere First some of the core language features that are available on all supported\u2026","rel":"","context":"In &quot;Android&quot;","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":1503,"url":"https:\/\/www.deltics.co.nz\/blog\/posts\/1503\/","url_meta":{"origin":2624,"position":4},"title":"Sharing Code Across Platforms in Oxygene","date":"22 Aug 2013","format":false,"excerpt":"There seems to be a perception among some people that Delphi is in the unique position of allowing developers to share and re-use code across the various platforms that it's compiler can now (and will soon) target. But this is not the case. Oxygene has had this capability right from\u2026","rel":"","context":"In &quot;Cooper&quot;","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":1199,"url":"https:\/\/www.deltics.co.nz\/blog\/posts\/1199\/","url_meta":{"origin":2624,"position":5},"title":"Oxygene &#8220;Nougat&#8221; is Mac and iOS !","date":"06 Sep 2012","format":false,"excerpt":"Marc Hoffman has confirmed that \"Nougat\" is to Mac\/iOS as \"Cooper\" was to Java. \u00a0Some have speculated that this will be based on Mono, but Oxygene has had Mono covered for some time already, so I strongly doubt that this is the case. Far more likely is that just as\u2026","rel":"","context":"In &quot;Delphi&quot;","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]}],"_links":{"self":[{"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/posts\/2624"}],"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=2624"}],"version-history":[{"count":7,"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/posts\/2624\/revisions"}],"predecessor-version":[{"id":2631,"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/posts\/2624\/revisions\/2631"}],"wp:attachment":[{"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/media?parent=2624"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/categories?post=2624"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/tags?post=2624"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}