{"id":750,"date":"2025-08-20T09:00:00","date_gmt":"2025-08-19T23:00:00","guid":{"rendered":"https:\/\/jm.armijo.au\/dev\/?p=750"},"modified":"2025-08-19T22:53:43","modified_gmt":"2025-08-19T12:53:43","slug":"inverting-logical-expressions","status":"publish","type":"post","link":"https:\/\/jm.armijo.au\/dev\/blog\/2025\/08\/20\/inverting-logical-expressions\/","title":{"rendered":"Inverting Logical Expressions"},"content":{"rendered":"\n<p>Part of our day-to-day tasks is to do code refactoring. As part of this process, I&#8217;m sure that many of us have had to negate the logical expressions in if or while statements at least once. For example, we may want to change this code:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: ruby; gutter: false; title: ; notranslate\" title=\"\">\nif logged_in\n  # do something when logged in\nelse\n  # do something when not logged in\nend\n<\/pre><\/div>\n\n\n<p>into something like this:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: ruby; gutter: false; title: ; notranslate\" title=\"\">\nif !logged_in\n  # do something when not logged in\nelse\n  # do something when logged in\nend\n<\/pre><\/div>\n\n\n<p>This is indeed a very simple change, so consider this other example:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: ruby; gutter: false; title: ; notranslate\" title=\"\">\n# Original\nif (age &gt;= 18 &amp;&amp; age &lt; 21)\n\n# Negated\nif !(age &gt;= 18 &amp;&amp; age &lt; 21)\n<\/pre><\/div>\n\n\n<p>This works and it&#8217;s perfectly valid, but it&#8217;s not always the best thing to do. Long expressions with a negation at the start are hard to read, and this is not the code I&#8217;d like to debug when there&#8217;s a production bug at 3 am.<\/p>\n\n\n\n<p>As you may have noticed already, this is a better way to negate that expression, as it greatly improves its readability:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: ruby; gutter: false; title: ; notranslate\" title=\"\">\nif age &lt; 18 || age &gt;= 21\n<\/pre><\/div>\n\n\n<p>And things may get more complicated as we add more conditions to our statement, like:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: ruby; gutter: false; title: ; notranslate\" title=\"\">\nif (admin || (retry &lt; 15 &amp;&amp; retry &gt;= 3)) &amp;&amp; !logged_in\n<\/pre><\/div>\n\n\n<p>The interesting thing is that we have a simple set of rules that dictate how to negate our conditions. Let me introduce you to De Morgan&#8217;s laws.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">The De Morgan&#8217;s Laws<\/h2>\n\n\n\n<p>Although Augustus De Morgan was not the first to come up with the laws that take his name, he is recognised for being the first to state them in terms of modern formal logic [1]. These rules can, however, be expressed in simple English as follows:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>The negation of &#8220;A and B&#8221; is the same as &#8220;not A or not B&#8221;.<\/li>\n\n\n\n<li>The negation of &#8220;A or B&#8221; is the same as &#8220;not A and not B&#8221;.<\/li>\n<\/ol>\n\n\n\n<p>In code, we could write them as:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: ruby; gutter: false; title: ; notranslate\" title=\"\">\n!(a &amp;&amp; b) == (!a || !b)\n!(a || b) == (!a &amp;&amp; !b)\n<\/pre><\/div>\n\n\n<p>Let&#8217;s consider some examples to see how these rules can be used:<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Applying The Laws<\/h2>\n\n\n\n<p>The first law is indeed very simple to apply:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: ruby; gutter: false; title: ; notranslate\" title=\"\">\n# Original\nif (logged_in &amp;&amp; has_permission)\n\n# Negated\nif !(logged_in &amp;&amp; has_permission)\n\n# Applying the first law\nif (!logged_in || !has_permission)\n<\/pre><\/div>\n\n\n<p>And so is the second:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: ruby; gutter: false; title: ; notranslate\" title=\"\">\n# Original\nif (email_valid || phone_valid)\n\n# Negated\nif !(email_valid || phone_valid)\n\n# Applying the second law\nif (!email_valid &amp;&amp; !phone_valid)\n<\/pre><\/div>\n\n\n<p>Things get more interesting with more complex expressions. In this example, we&#8217;ll negate an expression that combines &amp;&amp; and <code>||<\/code> operators. Note that in this example I apply the laws in two steps to show how the negation can be propagated into groups of parentheses, while having the same logical meaning at all times.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: ruby; gutter: false; title: ; notranslate\" title=\"\">\n# Original\nif (can_view || is_admin) &amp;&amp; status == &quot;active&quot;\n\n# Negated\nif !((can_view || is_admin) &amp;&amp; status == &quot;active&quot;)\n\n# Applying the laws\nif (!(can_view || is_admin)) || !(status == &quot;active&quot;)\nif (!can_view &amp;&amp; !is_admin) || status != &quot;active&quot;\n<\/pre><\/div>\n\n\n<p>We can also apply the law to relational operators, like in the example below:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: ruby; gutter: false; title: ; notranslate\" title=\"\">\n# Original\nif (age &gt;= 18 &amp;&amp; age &lt; 21)\n\n# Negated\nif !(age &gt;= 18 &amp;&amp; age &lt; 21)\n\n# Applying the laws\nif !(age &gt;= 18) || !(age &lt; 21)\nif age &lt; 18 || age &gt;= 21\n<\/pre><\/div>\n\n\n<h3 class=\"wp-block-heading\">Wrap Up<\/h3>\n\n\n\n<p>The De Morgan&#8217;s laws give us easy to follow steps to effortlessly invert the most complex logical expressions in our code.<\/p>\n\n\n\n<p>However, I&#8217;d be really worried if my code was full of lengthy, complex expressions. Maybe one or two are unavoidable, but if your conditional are growing big, consider refactoring your code to avoid them in the first place.<\/p>\n\n\n\n<p>If you decide to change your code, be it to invert a conditional or simplify it, I would highly recommend using unit tests to ensure that the code works as expected before and after the refactor, as no laws discovered to date are able to prevent human error.<\/p>\n\n\n\n<p>Cheers,<br>Jos\u00e9 Miguel<\/p>\n\n\n\n<p><em>Share if you find this content useful, and Follow me on&nbsp;<a href=\"http:\/\/www.linkedin.com\/comm\/mynetwork\/discovery-see-all?usecase=PEOPLE_FOLLOWS&amp;followMember=jmarmijo\">LinkedIn<\/a>&nbsp;to be notified of new articles.<\/em><\/p>\n\n\n\n<h3 class=\"wp-block-heading\">References<\/h3>\n\n\n\n<p><a href=\"https:\/\/archive.org\/details\/formallogicorthe00demouoft\/page\/118\/mode\/2up?utm_source=chatgpt.com&amp;view=theater\">[1]<\/a> Formal Logic: or, The Calculus of Inference, Necessary and Probable. De Morgan, 1847.<br><a href=\"https:\/\/en.wikipedia.org\/wiki\/De_Morgan%27s_laws\">[2]<\/a> De Morgan&#8217;s laws &#8211; Wikipedia<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Part of our day-to-day tasks is to do code refactoring. As part of this process, I&#8217;m sure that many of us have had to negate the logical expressions in if or while statements at least once. For example, we may want to change this code: into something like this: This is indeed a very simple [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":759,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-750","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/jm.armijo.au\/dev\/wp-json\/wp\/v2\/posts\/750","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/jm.armijo.au\/dev\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/jm.armijo.au\/dev\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/jm.armijo.au\/dev\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/jm.armijo.au\/dev\/wp-json\/wp\/v2\/comments?post=750"}],"version-history":[{"count":13,"href":"https:\/\/jm.armijo.au\/dev\/wp-json\/wp\/v2\/posts\/750\/revisions"}],"predecessor-version":[{"id":766,"href":"https:\/\/jm.armijo.au\/dev\/wp-json\/wp\/v2\/posts\/750\/revisions\/766"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/jm.armijo.au\/dev\/wp-json\/wp\/v2\/media\/759"}],"wp:attachment":[{"href":"https:\/\/jm.armijo.au\/dev\/wp-json\/wp\/v2\/media?parent=750"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/jm.armijo.au\/dev\/wp-json\/wp\/v2\/categories?post=750"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/jm.armijo.au\/dev\/wp-json\/wp\/v2\/tags?post=750"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}