# On the arbitrariness of truth(iness)

**URL:** <https://discourse.julialang.org/t/on-the-arbitrariness-of-truth-iness/81381>\
**Category:** Internals & Design\
**Created:** [May 20, 2022, 3:32pm UTC](https://discourse.julialang.org/t/on-the-arbitrariness-of-truth-iness/81381 "2022-05-20T15:32:55Z")\
**Posts on this page:** 12\
**Page:** 3

<div class="post-metadata">

**Author:** ![traktofon](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/traktofon/32/591_2.png) [@traktofon](https://discourse.julialang.org/u/traktofon)\
**Post date:** [May 23, 2022, 4:49pm UTC](https://discourse.julialang.org/t/on-the-arbitrariness-of-truth-iness/81381/45 "2022-05-23T16:49:59Z")

</div>

Another language (or whole family of languages) where the numeric values of true and false don’t follow the C convention is the Unix shell (e.g. bash). Admittedly, this works on program return codes, not variables’ values, but still:

```bash
$ true; echo $?
0
$ false; echo $?
1
$ if true; then echo yes; fi
yes

```

That is, only the return code zero is “true”.

---

<div class="post-metadata">

**Author:** ![jonathanBieler](https://avatars.discourse-cdn.com/v4/letter/j/82dd89/32.png) [@jonathanBieler](https://discourse.julialang.org/u/jonathanBieler)\
**Post date:** [May 23, 2022, 4:52pm UTC](https://discourse.julialang.org/t/on-the-arbitrariness-of-truth-iness/81381/46 "2022-05-23T16:52:09Z")

</div>

It also allows to do `mean(rand(1000) .> 0.5)` to count proportions, which I find quite convenient. I’m not sure what’s the use case for treating `Bool` as `Int1`.

---

<div class="post-metadata">

**Author:** ![StefanKarpinski](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stefankarpinski/32/24_2.png) [@StefanKarpinski](https://discourse.julialang.org/u/StefanKarpinski)\
**Post date:** [May 23, 2022, 5:37pm UTC](https://discourse.julialang.org/t/on-the-arbitrariness-of-truth-iness/81381/47 "2022-05-23T17:37:57Z")

</div>

> [@jonathanBieler](#):
>
> I’m not sure what’s the use case for treating `Bool` as `Int1` .

Especially since you can truncate to one bit at the end of any sequence of ring operations and get the same answer.

---

<div class="post-metadata">

**Author:** ![uniment](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/uniment/32/24532_2.png) [@uniment](https://discourse.julialang.org/u/uniment)\
**Post date:** [March 22, 2023, 5:39am UTC](https://discourse.julialang.org/t/on-the-arbitrariness-of-truth-iness/81381/48 "2023-03-22T05:39:30Z")

</div>

Since @jar1 thrust this conversation into discussing Boolean algebra, a field in which they recently [changed](https://discourse.julialang.org/t/add-varargs-methods-of-any-all-and-count/95072/27) my mind, I wanted to share some of these new thoughts.

TLDR: Corresponding false/true with 0/1 is arbitrary and awkward; it’s more coherent to use -inf/inf instead.

Like the truthy and falsy values of the OP, the choice to consider 0 falsy and 1 truthy is similarly arbitrary, and as this thread demonstrates it makes for an awkward algebra. There are other ways in which it’s awkward too: for example, _and_ (\wedge) and _or_ (\vee) are commonly considered analogous to multiplication and addition respectively, with [operator](https://en.wikipedia.org/wiki/Logical_connective#Order_of_precedence) [precedences](https://github.com/JuliaLang/julia/blob/master/src/julia-parser.scm#L23) reflecting that, yet they both distribute over each other (in contrast, numeric addition does _not_ distribute over multiplication!).

In these _Unified Algebra_ essays [1](http://www.cs.toronto.edu/~hehner/BAUA.pdf) and [2](https://www.cs.utoronto.ca/~hehner/UA.pdf), compsci prof Hehner at U of T argues that, to integrate Boolean algebra cleanly into our algebra of numbers, the numeric value corresponding to truth should be \top (the top of the number lattice, usually positive infinity), and the numeric value of falsity should be \bot (the bottom of the number lattice, usually negative infinity). Instead of the conjunction \wedge and disjunction \vee operators, use \downarrow (min) and \uparrow (max) respectively.

Then, where p,q\in\{\bot,\top\}, instead of p\wedge q (p and q) you’d write p \downarrow q (p min q), instead of p \vee q (p or q) you’d write p \uparrow q (p max q), and instead of p \veebar q (p xor q) you’d write p \ne q. Also, instead of p \implies q (p implies q) you’d write p \le q (p order q), instead of p \iff q (p iff q) you’d write p=q, and instead of writing DeMorgan’s laws as \neg(p\wedge q)\iff\neg p\vee\neg q and \neg(p\wedge q)\iff\neg p\vee\neg q, they’d be written: -(p\downarrow q)=-p\uparrow -q and -(p\uparrow q)=-p\downarrow -q. Notice that all the operators—min, max, negation, and comparisons—are in common with regular numeric algebra.

Mathematically, I like that this concept unifies Boolean algebra with numeric algebra. Epistemologically, I like that whatever discomfort people have toward the concept of infinity, they should rightly have toward the attainability of certain truth (an attitude of _humility_). And practically, with a background in analog chips, I like that this concept is reflective of the circuits we design to convert a continuous signal into a binary one: comparators, circuits which ideally have _infinite gain_ about their decision point, whose output saturates at finite V\_L and V\_H out of practical necessity but which otherwise could be thought of as returning V\_\bot or V\_\top. Also, the designs of _and_ and _or_ gates are complementary; it’s strange for one to correspond to an operator with higher precedence than the other (mobility \mu\_e/\mu\_h notwithstanding).

It’s a major departure from popular languages though, so I don’t think we’ll see it anytime soon, but dropping other silly notions of truthy and falsy is a good start. Maybe in Julia 3.0 😉

---

<div class="post-metadata">

**Author:** ![bertschi](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bertschi/32/33462_2.png) [@bertschi](https://discourse.julialang.org/u/bertschi)\
**Post date:** [March 22, 2023, 8:20pm UTC](https://discourse.julialang.org/t/on-the-arbitrariness-of-truth-iness/81381/49 "2023-03-22T20:20:00Z")

</div>

What you are describing appears equivalent to a fuzzy logic, i.e., an extension of Boolean logic to real truth values in [0, 1]. Common choices include, p \land q = p \min q, \; p \lor q = p \max q or p \land q = p \cdot q, \; p \lor q = p + q - p \cdot q.  
In general, \land is replaced by a so called t-norm and \lor the corresponding t-conorm conforming with De-Morgan’s law under the negation \lnot p = 1 - p, i.e., p t-conorm q = 1 - ((1 - p) t-norm (1 - q)).  
The version you state above is equivalent to the max/min version under the mapping [0, 1] \to \mathbb{R} via the monotone function p \mapsto \log(\frac{p}{1-p}), i.e., identifying 0 and 1 with negative and positive infinity respectively.  
In any case, not all laws of Boolean logic carry over to the extension, e.g., losing the law of excluded middle p \lor \lnot p \equiv T \; \forall p which was a major motivation for developing fuzzy logic in the first place.

Another approach is taken by the [J](https://code.jsoftware.com/wiki/NuVoc) programming language where `and` and `or` are extended as the `lcm` (least common multiple) and `gcd` (greatest common divisor) respectively – I’m not sure about the rationality/implications of that choice though.

---

<div class="post-metadata">

**Author:** ![uniment](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/uniment/32/24532_2.png) [@uniment](https://discourse.julialang.org/u/uniment)\
**Post date:** [March 22, 2023, 11:28pm UTC](https://discourse.julialang.org/t/on-the-arbitrariness-of-truth-iness/81381/50 "2023-03-22T23:28:36Z")

</div>

> [@bertschi](#):
>
> What you are describing appears equivalent to a fuzzy logic, i.e., an extension of Boolean logic to real truth values in [0, 1]

Not quite. Indeed, it carries similarities such as using \max and \min, and involves a mapping of [0,1]\rightarrow\mathbb R (which exact mapping I’m not sure, but p\mapsto\log\left(\frac{p}{1-p}\right) seems reasonable). But it still has only two values, and the law of excluded middle remains: for p \in \{\bot, \top\}, p\uparrow -p = \top.

In Hehner’s formulation, if you wish to lose the law of excluded middle, the first thing to do would be to introduce a zero value such that p\in\{\bot,0,\top\}, making it a three-valued algebra. Or for full fuzziness, let p\in\mathbb R.

---

<div class="post-metadata">

**Author:** ![haberdashPI](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/haberdashpi/32/26337_2.png) [@haberdashPI](https://discourse.julialang.org/u/haberdashPI)\
**Post date:** [March 23, 2023, 3:39pm UTC](https://discourse.julialang.org/t/on-the-arbitrariness-of-truth-iness/81381/51 "2023-03-23T15:39:18Z")

</div>

> [@uniment](#):
>
> Corresponding false/true with 0/1 is arbitrary and awkward;

Not exactly, there’s a pretty solid connection: [Boolean algebra - Wikipedia](https://en.m.wikipedia.org/wiki/Boolean_algebra)

---

<div class="post-metadata">

**Author:** ![uniment](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/uniment/32/24532_2.png) [@uniment](https://discourse.julialang.org/u/uniment)\
**Post date:** [March 23, 2023, 8:54pm UTC](https://discourse.julialang.org/t/on-the-arbitrariness-of-truth-iness/81381/52 "2023-03-23T20:54:39Z")

</div>

Good point, it looks like that Wikipedia article needs to be edited 😉

---

<div class="post-metadata">

**Author:** ![bertschi](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bertschi/32/33462_2.png) [@bertschi](https://discourse.julialang.org/u/bertschi)\
**Post date:** [March 23, 2023, 10:49pm UTC](https://discourse.julialang.org/t/on-the-arbitrariness-of-truth-iness/81381/53 "2023-03-23T22:49:24Z")

</div>

Should have been more precise: Any fuzzy logic reduces exactly to Boolean logic when restricted to the truth values \bot and \top (usually represented as 0 and 1 or negative and positive infinity in your case). The law of excluded middle (and possibly other laws as well) are lost as soon as additional values, e.g., 0.5, 0.1 etc., are introduced.  
What I wanted to stress is that there are many ways (fuzzy logics) extending Boolean logic, i.e., identical on \top and \bot alone, but with different properties on other values. In the end, the algebra on real numbers is not a Boolean algebra and every embedding has its pros and cons. On the other hand, just identifying \top and \bot with 1 and 0 does not aim to embed the Boolean algebraic structure in any meaningful way. Instead, I tend to think of it as a short-hand notation for the indicator function or [Iverson bracket](https://en.wikipedia.org/wiki/Iverson_bracket) which is quite handy for arithmetic involving Boolean conditions, e.g., `abs(x) = x * (x > 0) - x * (x < 0)`.

---

<div class="post-metadata">

**Author:** ![uniment](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/uniment/32/24532_2.png) [@uniment](https://discourse.julialang.org/u/uniment)\
**Post date:** [March 25, 2023, 5:43am UTC](https://discourse.julialang.org/t/on-the-arbitrariness-of-truth-iness/81381/54 "2023-03-25T05:43:05Z")

</div>

I should mention another philosophical benefit of identifying logical \{\bot,\top\} with numeric \{-\infty, +\infty\}.

In the field of communication, detecting a binary symbol entails roughly demodulating and filtering of some sort, followed by (for phased arrays) a projection from a high-dimensional space to a scalar, followed by a comparison against a threshold.

A natural question should be: what is the _ideal_ binary symbol? Well, it’d be the one that can be subject to any degree of noise pollution as it propagates through the channel, and still maintain zero transmission errors—there should be infinite spacing between symbols. The natural answer is an infinite signal in \{\bot,\top\}.

In practice one must of course trade off the various limitations that don’t permit real signals to have infinite (or negative) power or bandwidth, but the notion of an ideal is generally a useful mental tool.

> [@bertschi](#):
>
> just identifying \top and \bot with 1 and 0 does not aim to embed the Boolean algebraic structure in any meaningful way. Instead, I tend to think of it as a short-hand notation for the indicator function or [Iverson bracket](https://en.wikipedia.org/wiki/Iverson_bracket) which is quite handy for arithmetic involving Boolean conditions, e.g., `abs(x) = x * (x > 0) - x * (x < 0)`.

This is a good perspective—identifying logical \{\bot,\top\} with \{0,1\} isn’t the most philosophically coherent, but it makes the Iverson bracket implicit, which is handy practically. It means Boolean vectors implicitly serve the role of indicator functions, which is also handy.

Maybe if Julia had a nice indicator function/explicit Iverson bracket, we could work around this. The parsing rules around numeric literals make it difficult to use `1` as an Iverson bracket. Then again, the implicit Iverson bracket sure is handy for [Code Golf](https://discourse.julialang.org/t/code-golfing-fizzbuzz/95354/1).

---

<div class="post-metadata">

**Author:** ![jar1](https://avatars.discourse-cdn.com/v4/letter/j/c0e974/32.png) [@jar1](https://discourse.julialang.org/u/jar1)\
**Post date:** [March 25, 2023, 6:22am UTC](https://discourse.julialang.org/t/on-the-arbitrariness-of-truth-iness/81381/55 "2023-03-25T06:22:35Z")

</div>

There’s a bold `𝟏` (`\bfone`)

```julia
𝟏(x::Bool) = x ? 1 : 0
julia> 𝟏(3 < 4)
1

```

> [@uniment](#):
>
> It means Boolean vectors implicitly serve the role of indicator functions, which is also handy.

I didn’t get this point. What does it look like in code?

---

<div class="post-metadata">

**Author:** ![uniment](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/uniment/32/24532_2.png) [@uniment](https://discourse.julialang.org/u/uniment)\
**Post date:** [March 25, 2023, 7:04am UTC](https://discourse.julialang.org/t/on-the-arbitrariness-of-truth-iness/81381/56 "2023-03-25T07:04:13Z")

</div>

I suppose there’s also a hypothetical future in which Julia’s parsing rules change such that numeric literals are callable. Then it’d be trivial to define:

```julia
(x::Number)(y::Number) = x*y # for backwards-compatibility
(x::Number)(b::Bool) = b ? x : zero(x) # for indication

```

In addition to `1(p::Bool)` serving as an indicator, this concept also has the advantage(?) that the product `(a+b)(c+d)` would become valid.

> [@jar1](#):
>
> What does it look like in code?

Suppose I wish to calculate the sum of non-negative values of `xs`. Since indicating is implicit, I might write:

```julia
(xs .≥ 0)' * xs

```

If `Bool` identified with infinite values, we’d need an explicit indicator and be forced to write a longer expression such as:

```julia
1.(xs .≥ 0)' * xs

```

[Previous page](https://discourse.julialang.org/t/on-the-arbitrariness-of-truth-iness/81381.md?page=2)
