I started to write a test script for "Boolean Operators" with and w/o "Short-Circuit" in Perl.
And quickly found me needing to define and test "Truthiness" in Perl.
(Wait ... "0 but true" is false? Remembered it differently ;-)
And now I find myself obliged to also define "Contexts", because an empty list is also false.
And "Data Types", because internally it's more difficult, than just Scalar, Array and Hash.
It's a lot of work, but in the end it could help in many corners when done correctly:
Like so often, after a first success I find myself a bit stuck in the big picture.
I'll throw in my first approach as is for meditation.
There is a lot to be criticized, but my normal perfectionism is too risky and might lead to a never release cycle.
Thoughts?
Cheers Rolf
(addicted to the Perl Programming Language :)
Wikisyntax for the Monastery
FootballPerl is like chess, only without the dice
use strict; use warnings; use Data::Dump qw/pp dd/; use Scalar::Util qw/isdual/; use Test::More; =head1 Boolean Operations in Perl =head2 True and False values Perl has no boolean datatype but a "boolean context" where other values evaluate to true or false. Operands can be literal values like depending on context. - strings - numbers Lists are converted to scalars Perl variables have 3 main datatypes: Scalars, Arrays and Hashes. The boolean context is just a specialized scalar context and the literal empty list C<()> evaluates to false. Arrays and Hashes are false iff they are empty. Scalar values are internally represented - strings - integers - float (double precission) - references/objects - undefined But Perl allows to use them all interchangabliy by casting them automa +tically. 1. Literal "nothing" is always false - C<undef> in scalar context - empty list, either implicit C<return;> or explicit C<()> NB: a non-empty list is always true, even if the elements are false like in C<return undef> 2. The neutral element of every internal datatype is FALSE: - i.e. all literal zeroes for numbers 0, 0.0, 0e0 - the empty string '' - empty arrays and hashes NB: The "0" string is also false, because Perl treats 0 and "0" to be the same scalar. But "0.0" or "0E0" are never false, these are literal notations. 3. References including those blessed to objects are always true. NB: You can treach with C<use overload> to make objects false. =cut =head2 Boolean return values Most Boolean operators like C<!> for C<not> return a "default scalar" as represntative for true and false. These can be easily construted by double negation false := !!0 true := !!1 But so called "Short-circuit Operators" change the control-flow. They return the last evaluated side instead, which is guarantied to be logically correct (later more) =cut my @false = ( !!0, # default 0, 0.0, 0e0, 0e10, "0", # scalar zeroes '', # empty string undef, # undef !!(), # empty list ); # NB: you can fake "false" objects by using =overload= sub is_FALSE { return unless isdual($_[0]) ; my $num = $_[0]; my $str = $_[0]; return ($num == 0) && ($str eq ""); } cmp_ok ( !!0, "==", 0, "!!0 is 0 in numeric context"); cmp_ok ( !!0, "eq", "", "!!0 is '' in string context"); ok ( is_FALSE(!!0)); # anything else is true my @true = ( !!1, # default 1 , "A", "0abc", "0 but true", "0e0", # all strings except "0" \0, [], {}, # refs (including blessed obje +cts) ); cmp_ok ( !!1, "==", 1, "!!1 == 1 in numeric context"); cmp_ok ( !!1, "eq", 1, "!!1 eq 1 in string context"); cmp_ok ( !!1, "eq", '1', "!!1 eq '1' in string context"); for my $x ( @true ) { ok ( $x, "true: ". pp($x) ); } for my $x ( @false ) { ok ( ! $x, "false: ". pp($x) ); } #done_testing(); #exit; =head2 short-circuit operators =cut my @values = (@false, @true); warn pp \@values; for my $x ( @values ) { for my $y ( @values ) { is( ($x || $y), ($x ? $x : $y), "|| " .pp($x,$y) . " => " . pp ($x || $y) ); } } for my $x ( @values ) { for my $y ( @values ) { is( ($x && $y), (!$x ? $x : $y), "&& ".pp($x,$y) . " => " . pp ($x && $y) ); } } for my $x ( @values ) { for my $y ( @values ) { is( ($x // $y), ( (defined $x) ? $x : $y), "// ".pp($x,$y) . " => " . pp ($x && $y) ); } } done_testing();
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re: Defining, Testing and Documenting Perl?
by Tux (Canon) on Dec 23, 2019 at 20:37 UTC | |
by tobyink (Canon) on Dec 23, 2019 at 22:00 UTC | |
by LanX (Saint) on Dec 24, 2019 at 00:41 UTC | |
by tobyink (Canon) on Dec 24, 2019 at 01:13 UTC | |
by LanX (Saint) on Dec 24, 2019 at 02:09 UTC | |
| A reply falls below the community's threshold of quality. You may see it by logging in. |