{"id":2597,"date":"2017-03-17T06:56:24","date_gmt":"2017-03-16T18:56:24","guid":{"rendered":"https:\/\/www.deltics.co.nz\/blog\/?p=2597"},"modified":"2017-03-17T07:50:48","modified_gmt":"2017-03-16T19:50:48","slug":"true-1-and-true-1","status":"publish","type":"post","link":"https:\/\/www.deltics.co.nz\/blog\/posts\/2597\/","title":{"rendered":"(True = 1) and (True = &#8216;-1&#8217;) ?"},"content":{"rendered":"<span class=\"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>It has been observed that the <a href=\"http:\/\/docwiki.embarcadero.com\/RADStudio\/Seattle\/en\/Simple_Types#Boolean_Types\">Delphi documentation states<\/a> that the constants <strong>True<\/strong> and <strong>False <\/strong>have the values <strong>1<\/strong> and <strong>0<\/strong> respectively, not the <strong>-1<\/strong> and <strong>0<\/strong> that the default string conversions apply.  This does actually make sense but also lays a trap for the unwary.<\/p>\n<p><!--more--><\/p>\n<h2> True, True, Wherefore Art Thou &#8216;-1&#8217; ? <\/h2>\n<p>In <a href=\"http:\/\/docwiki.embarcadero.com\/RADStudio\/Seattle\/en\/Simple_Types#Boolean_Types\">the Simple Types documentation<\/a> it is stated that any <em>non-zero value<\/em> is logically true.  But in <a href=\"http:\/\/docwiki.embarcadero.com\/Libraries\/Seattle\/en\/System.Boolean\">the documentation for the Boolean type itself<\/a> it is stated that only <em>ordinal value 1<\/em> is considered true.<\/p>\n<p>But if <strong>True<\/strong> has the <em>explicit<\/em> value <strong>1<\/strong> why does <strong>BoolToStr(True)<\/strong> return <strong>&#8216;-1&#8217;<\/strong> and not simply <strong>&#8216;1&#8217;<\/strong> ?<\/p>\n<p>Well, in one key respect the documentation for the <strong>Boolean<\/strong> type is simply wrong.<\/p>\n<p>In fact, <em>any non-zero value<\/em> is <em>logically<\/em> true, not just 1.  i.e. the <strong>Simple Types<\/strong> documentation is correct on this point, as we can easily demonstrate:<\/p>\n<pre class=\"brush: delphi; title: ; notranslate\" title=\"\">\r\n   procedure TestBoolean;\r\n   var\r\n     b: Boolean;\r\n   begin\r\n     b := Boolean(42);\r\n\r\n     if b then\r\n       ShowMessage('42 is True!');\r\n   end;\r\n<\/pre>\n<p>Run this and you <em>will<\/em> see the message.<\/p>\n<p>And this leads us to an understanding of why <strong>BoolToStr(True)<\/strong> might reasonably return <strong>&#8216;-1&#8217;<\/strong>.<\/p>\n<p>Regardless of the specific size of <strong>Boolean<\/strong> type involved (Byte, Word, Long etc), any non-zero value must have <em>at least<\/em> one bit set and may have <em>more<\/em> than one bit set.  So it makes a certain amount of sense to say that a logical <strong>True<\/strong> is equivalent to a value where <strong>all<\/strong> possible bits are set, since any of them <em>could<\/em> be for any particular logically true value.<\/p>\n<p><strong>And in <a href=\"https:\/\/en.wikipedia.org\/wiki\/Two's_complement\">Two&#8217;s Complement<\/a> notation, an integer with all bits set has the value -1.<\/strong><\/p>\n<p>That&#8217;s one way to think about it.  But the Two&#8217;s Complement rationale also applies when considering Booleans as strictly, well, Boolean.  \ud83d\ude42<\/p>\n<p><strong>False<\/strong> has ordinality <strong>0<\/strong> and since <strong>True<\/strong> is the <em>logical negation<\/em> of <strong>False<\/strong> then if we flip all the bits in any sized value of <strong>False<\/strong> (0) then we again end up with all bits set which in Two&#8217;s Complement again yields <strong>-1<\/strong>.<\/p>\n<p>Ta-dah!<\/p>\n<h2> A Question for the Ages&#8230; <\/h2>\n<p>Perhaps the real question is why <strong>True<\/strong> was ever defined with ordinality of <strong>1<\/strong> in the first place, and not <strong>-1<\/strong> ?<\/p>\n<p>I honestly don&#8217;t know, but suspect that it likely goes back to the origins of Pascal in the 1970&#8217;s and the introduction of Boolean as a formal enumerated type, thus determining the ordinality of the members as 0 and 1.<\/p>\n<p>This might also explain some of the enum-like capabilities\/compatibility of <strong>Boolean<\/strong> in Delphi, whilst clearly not behaving as an enum in some key respects.<\/p>\n<p>The similarities:<\/p>\n<ul>\n<li>Boolean values in RTTI are of <strong>TypeKind<\/strong> <em>tkEnumeration<\/em><\/li>\n<li>GetEnumName\/Value support Boolean types\/values<\/li>\n<\/ul>\n<p>The differences:<\/p>\n<ul>\n<li>GetEnumName\/Value support Boolean types\/values as <strong>special cases<\/strong><\/li>\n<li>In more recent versions of Delphi, Boolean types support <strong>ToString()<\/strong> (enumerated types do not)<\/li>\n<li>Coercing an ordinal value in an enum that is not a defined member yields an out of bounds value (not an error, just an &#8220;unnamed&#8221; or undefined member)<\/li>\n<li>Coercing an ordinal value in a Boolean that is not a defined member yields a logical member (True)<\/li>\n<\/ul>\n<p>Also worth noting is that <strong>GetEnumName\/Value<\/strong> also support <strong>Integer<\/strong> types, so those old <strong>TypInfo<\/strong> &#8220;Enum&#8221; functions are obviously not <em>just<\/em> for enumerated types.<\/p>\n<p>In addition, in one branch of the special case handling for Boolean, <strong>GetEnumValue<\/strong> explicitly yields <strong>-1<\/strong> for <strong>True<\/strong> values, despite the documentation (and presumably the compiler) using <strong>1<\/strong>.  i.e. this particular enum function contrives to contradict the &#8220;definition&#8221; of this particular enum.<\/p>\n<h2> It&#8217;s A Trap! <\/h2>\n<p>The trap I mentioned at the beginning arises from a compiler behaviour and a rather misleading (at best, incorrect at worst) statement in the Simple Types documentation:<\/p>\n<blockquote><p>A [Boolean] is considered True when its ordinality is non-zero.  If such a value appears in a context where a Boolean is expected, the compiler automatically converts any value of nonzero ordinality to True.<\/p><\/blockquote>\n<p>The problem is that inference that non-zero values are &#8220;automatically converted&#8221; to the <strong>value<\/strong> <em>True<\/em>, which we are told has <strong>ordinality of 1<\/strong>.<\/p>\n<p>This is not always the case.<\/p>\n<p>Again, we can demonstrate this very easily with a small change to that previous snippet of code:<\/p>\n<pre class=\"brush: delphi; title: ; notranslate\" title=\"\">\r\n   procedure TestBoolean;\r\n   var\r\n     b: Boolean;\r\n   begin\r\n     b := Boolean(42);\r\n\r\n     if b then\r\n       ShowMessage('42 is True!');\r\n\r\n     if b = True then\r\n       ShowMessage('b = True!');\r\n   end;\r\n<\/pre>\n<p>In this case, you will <strong>not<\/strong> see the second message.<\/p>\n<p>The Boolean evaluates as <em>logically true<\/em> but it does <em>not<\/em> have the same ordinal value as <strong>True<\/strong>.  The compiler does <strong>not<\/strong> convert the Boolean value with ordinality 42 to the value <strong>True <\/strong>(1) at all.<\/p>\n<p>Things get even more interesting if you start changing the ordinality of the Boolean in order to figure out exactly what the compiler does consider to be equal to <strong>True<\/strong>.  So, for example, to test that the compiler really is using ordinal 1 for <strong>True<\/strong>:<\/p>\n<pre class=\"brush: delphi; title: ; notranslate\" title=\"\">\r\n   procedure TestBoolean;\r\n   var\r\n     b: Boolean;\r\n   begin\r\n     b := Boolean(1);  \/\/ Or 1 or any b &lt; 0\r\n\r\n     if b then\r\n       ShowMessage('b is True!');  \r\n\r\n     if b = True then\r\n       ShowMessage('b = True!'); \/\/ Is shown for b = 1 and all b &lt; 0 but not b &gt; 1\r\n   end;\r\n<\/pre>\n<p>Plugging in some additional values, it turns out that <strong>b = True<\/strong> for <strong>b = 1<\/strong> and <strong>b < 0<\/strong> but <em>not<\/em> <strong>b > 1<\/strong>.<\/p>\n<p>The trap that this lays is that you might be forgiven for thinking that explicit tests for equality with Boolean constants <strong>True <\/strong> and\/or <strong>False<\/strong> are simply redundant noise, but in fact in the case of comparisons with <strong>True<\/strong> this can obviously introduce subtle but significant bugs. <\/p>\n<h2> Delphi Language Feature:  Truthiness <\/h2>\n<p>In Delphi, you can even appear to have <strong>extremely<\/strong> true values:<\/p>\n<pre class=\"brush: delphi; title: ; notranslate\" title=\"\">\r\n   procedure TestBoolean;\r\n   var\r\n     b: Boolean;\r\n   begin\r\n     b := Boolean(42);\r\n\r\n     if b then\r\n       ShowMessage('42 is True!');\r\n\r\n     if b = True then\r\n       ShowMessage('b = True!');\r\n\r\n     if b &gt; True then\r\n       ShowMessage('b is more true than True itself!!');\r\n   end;\r\n<\/pre>\n<h2> Oxygene Variations <\/h2>\n<p>For developers using the <a href=\"http:\/\/www.elementscompiler.com\/elements\/oxygene\/\">Oxygene<\/a> implementation of ObjectPascal I would note at this point that the same behaviour w.r.t <strong>=<\/strong> applies on .net but on Java <strong>b = true<\/strong> <em>is<\/em> just as logically true in this case as <strong>b<\/strong> itself.<\/p>\n<pre class=\"brush: oxygene; title: ; notranslate\" title=\"\">\r\n   procedure TestBoolean;\r\n   begin\r\n     var b := Boolean(42);\r\n\r\n     if b then\r\n       WriteLn('42 is True!');  \/\/ Yes it is\r\n\r\n     if b = True then\r\n       WriteLn('b = True!');    \/\/ Not on .net, but yes indeed on Java\r\n\r\n     if b &gt; True then           \/\/ ERR: Does not compute!\r\n       WriteLn('b is more true than True itself!!');\r\n   end;\r\n<\/pre>\n<p>I don&#8217;t know whether this equality comparison difference is an edge-case bug in the compiler or simply a consequence of variations in the type systems on the underlying platforms and I haven&#8217;t (yet) tested on Cocoa.<\/p>\n<p>However, in all cases the <strong>Oxygene<\/strong> compiler will reject the use of the <strong>&gt;<\/strong> operator on <strong>Boolean<\/strong> types, so you cannot fall into that particular aspect of the trap with Oxygene.<\/p>\n<h2> Conclusion <\/h2>\n<p>The seeming schizophrenia of <strong>True<\/strong> identifying as both <strong>1<\/strong> and <strong>-1<\/strong> is not as crazy as it might at first seem, but when it comes to directly comparing for equality with <strong>True<\/strong> the safest approach is simply <strong>don&#8217;t<\/strong>.<\/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\">4<\/span> <span class=\"rt-label rt-postfix\">minutes]<\/span><\/span> 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.<\/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,180],"tags":[316,292,13,181],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/p1TKYv-FT","jetpack_sharing_enabled":true,"jetpack-related-posts":[{"id":2265,"url":"https:\/\/www.deltics.co.nz\/blog\/posts\/2265\/","url_meta":{"origin":2597,"position":0},"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":2605,"url":"https:\/\/www.deltics.co.nz\/blog\/posts\/2605\/","url_meta":{"origin":2597,"position":1},"title":"The Varying (and Variant) Value of True","date":"21 Mar 2017","format":false,"excerpt":"My most recent posts have prompted a bit of discussion, and it seems some concern, regarding the implementation of Boolean values in Delphi. The concern at least I think is unwarranted, as long as you avoid explicitly comparing a Boolean value to the True constant and allow the compiler to\u2026","rel":"","context":"In &quot;Delphi&quot;","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":2624,"url":"https:\/\/www.deltics.co.nz\/blog\/posts\/2624\/","url_meta":{"origin":2597,"position":2},"title":"Expressive If and Case &#8230;","date":"25 Apr 2017","format":false,"excerpt":"A quick post on a small but hugely useful little language feature in Oxygene... if expressions. Many people will be familiar with the so-called ternary operator. Delphi developers will also be aware that there is no direct equivalent in Delphi. In 'C' and other languages we can write a statement\u2026","rel":"","context":"In &quot;Delphi&quot;","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":2337,"url":"https:\/\/www.deltics.co.nz\/blog\/posts\/2337\/","url_meta":{"origin":2597,"position":3},"title":"A Silent Danger&#8230;","date":"07 Jun 2015","format":false,"excerpt":"A brief post on a long standing omission in type checking in Pascal and the limitations of Range Checking as applied to the problem. Consider this contrived example of a simple function: This very simple function accepts an explicitly 32-bit Integer parameter and simply returns TRUE if the value passed\u2026","rel":"","context":"In &quot;Delphi&quot;","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":1207,"url":"https:\/\/www.deltics.co.nz\/blog\/posts\/1207\/","url_meta":{"origin":2597,"position":4},"title":"Adventures in Syntax: Something Old, Something New etc&#8230;","date":"20 Sep 2012","format":false,"excerpt":"As the post title says, this will be a brief detour through some features of the Pascal language and a presentation of some (theoretical) alternatives that could have been introduced instead. That is, some are real but little known syntax, others are what I think might be preferable to the\u2026","rel":"","context":"In &quot;Delphi&quot;","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":2584,"url":"https:\/\/www.deltics.co.nz\/blog\/posts\/2584\/","url_meta":{"origin":2597,"position":5},"title":"Anatomy of a utility function:  BoolToStr()","date":"16 Mar 2017","format":false,"excerpt":"Jaap Van Goor was asking on FaceBook about some seemingly strange behaviour when obtaining string representations of Booleans using the Delphi RTL, which led me to revisit some familiar (and some not so familiar) old Delphi ground and take a look at the area involved in further detail. First of\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\/2597"}],"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=2597"}],"version-history":[{"count":7,"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/posts\/2597\/revisions"}],"predecessor-version":[{"id":2604,"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/posts\/2597\/revisions\/2604"}],"wp:attachment":[{"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/media?parent=2597"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/categories?post=2597"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/tags?post=2597"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}