Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Perl booleans, negation (and how to explain it)?

Tags:

perl

I'm new here. After reading through how to ask and format, I hope this will be an OK question. I'm not very skilled in perl, but it is the programming language what I known most.

I trying apply Perl to real life but I didn't get an great understanding - especially not from my wife. I tell her that:

if she didn't bring to me 3 beers in the evening, that means I got zero (or nothing) beers.

As you probably guessed, without much success. :(

Now factually. From perlop:

Unary "!" performs logical negation, that is, "not".

Languages, what have boolean types (what can have only two "values") is OK:

if it is not the one value -> must be the another one.

so naturally:

!true  -> false
!false -> true

But perl doesn't have boolean variables - have only a truth system, whrere everything is not 0, '0' undef, '' is TRUE. Problem comes, when applying logical negation to an not logical value e.g. numbers.

E.g. If some number IS NOT 3, thats mean it IS ZERO or empty, instead of the real life meaning, where if something is NOT 3, mean it can be anything but 3 (e.g. zero too).

So the next code:

use 5.014;
use Strictures;

my $not_3beers = !3;

say defined($not_3beers) ? "defined, value>$not_3beers<" : "undefined";
say $not_3beers ? "TRUE" : "FALSE";

my $not_4beers = !4;
printf qq{What is not 3 nor 4 mean: They're same value: %d!\n}, $not_3beers if( $not_3beers == $not_4beers );
say qq(What is not 3 nor 4 mean: @{[ $not_3beers ? "some bears" : "no bears" ]}!) if( $not_3beers eq $not_4beers );

say ' $not_3beers>',  $not_3beers, "<";
say '-$not_3beers>', -$not_3beers, "<";
say '+$not_3beers>', -$not_3beers, "<";

prints:

defined, value><
FALSE
What is not 3 nor 4 mean: They're same value: 0!
What is not 3 nor 4 mean: no bears!
 $not_3beers><
-$not_3beers>0<
+$not_3beers>0<

Moreover:

perl -E 'say !!4'

what is not not 4 IS 1, instead of 4!

The above statements with wife are "false" (mean 0) :), but really trying teach my son Perl and he, after a while, asked my wife: why, if something is not 3 mean it is 0 ? .

So the questions are:

  • how to explain this to my son
  • why perl has this design, so why !0 is everytime 1
  • Is here something "behind" what requires than !0 is not any random number, but 0.
  • as I already said, I don't know well other languages - in every language is !3 == 0?
like image 309
elfiress Avatar asked Jul 05 '13 14:07

elfiress


1 Answers

I think you are focussing to much on negation and too little on what Perl booleans mean.

Historical/Implementation Perspective

What is truth? The detection of a higher voltage that x Volts.

On a higher abstraction level: If this bit here is set.

The abstraction of a sequence of bits can be considered an integer. Is this integer false? Yes, if no bit is set, i.e. the integer is zero.

A hardware-oriented language will likely use this definition of truth, e.g. C, and all C descendants incl Perl.

The negation of 0 could be bitwise negation—all bits are flipped to 1—, or we just set the last bit to 1. The results would usually be decoded as integers -1 and 1 respectively, but the latter is more energy efficient.

Pragmatic Perspective

It is convenient to think of all numbers but zero as true when we deal with counts:

my $wordcount = ...;

if ($wordcount) {
  say "We found $wordcount words";
} else {
  say "There were no words";
}

or

say "The array is empty" unless @array;  # notice scalar context

A pragmatic language like Perl will likely consider zero to be false.

Mathematical Perspective

There is no reason for any number to be false, every number is a well-defined entity. Truth or falseness emerges solely through predicates, expressions which can be true or false. Only this truth value can be negated. E.g.

¬(x ≤ y) where x = 2, y = 3

is false. Many languages which have a strong foundation in maths won't consider anything false but a special false value. In Lisps, '() or nil is usually false, but 0 will usually be true. That is, a value is only true if it is not nil!

In such mathematical languages, !3 == 0 is likely a type error.

Re: Beers

Beers are good. Any number of beers are good, as long as you have one:

my $beers = ...;

if (not $beers) {
  say "Another one!";
} else {
  say "Aaah, this is good.";
}

Boolification of a beer-counting variable just tells us if you have any beers. Consider !! to be a boolification operator:

my $enough_beer = !! $beers;

The boolification doesn't concern itself with the exact amount. But maybe any number ≥ 3 is good. Then:

my $enough_beer = ($beers >= 3);

The negation is not enough beer:

my $not_enough_beer = not($beers >= 3);

or

my $not_enough_beer = not $beers;

fetch_beer() if $not_enough_beer;

Sets

A Perl scalar does not symbolize a whole universe of things. Especially, not 3 is not the set of all entities that are not three. Is the expression 3 a truthy value? Yes. Therefore, not 3 is a falsey value.

The suggested behaviour of 4 == not 3 to be true is likely undesirable: 4 and “all things that are not three” are not equal, the four is just one of many things that are not three. We should write it correctly:

4 != 3    # four is not equal to three

or

not( 4 == 3 )   # the same

It might help to think of ! and not as logical-negation-of, but not as except.

How to teach

It might be worth introducing mathematical predicates: expressions which can be true or false. If we only ever “create” truthness by explicit tests, e.g. length($str) > 0, then your issues don't arise. We can name the results: my $predicate = (1 < 2), but we can decide to never print them out, instead: print $predicate ? "True" : "False". This sidesteps the problem of considering special representations of true or false.

Considering values to be true/false directly would then only be a shortcut, e.g. foo if $x can considered to be a shortcut for

foo if defined $x and length($x) > 0 and $x != 0;

Perl is all about shortcuts.

Teaching these shortcuts, and the various contexts of perl and where they turn up (numeric/string/boolean operators) could be helpful.

  • List Context
    • Even-sized List Context
  • Scalar Context
    • Numeric Context
    • String Context
    • Boolean Context
  • Void Context
like image 100
amon Avatar answered Sep 28 '22 06:09

amon