{"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=\"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>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=\"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>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_newsletter_access":"","_jetpack_dont_email_post_to_subs":true,"_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":true,"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,180],"tags":[316,292,13,181],"class_list":["post-2597","post","type-post","status-publish","format-standard","hentry","category-delphi","category-oxygene","tag-boolean","tag-delphi","tag-language","tag-oxygene-2"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/p1TKYv-FT","jetpack_sharing_enabled":true,"jetpack-related-posts":[],"_links":{"self":[{"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/posts\/2597","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=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}]}}