The value of Truth

K

kj

The if procedure Test::eek:k is given 3 arguments, it evaluates the
first 2 arguments, tests to see if they are equal (using eq), and
prints a message involving the 3rd argument if they are not.

Supposing that we wanted a test that succeeded if foo() > 0, and
having the message upon failure contain the string "bad foo". One
could use something like ok(foo() > 0, 1, 'bad foo'), on the
assumption that if foo() > 0 was true it would evaluate to 1.

I remember reading somewhere that it was bad form to assume any
particular value for a truth value in Perl, because the implementation
reserved the right to change this value.

But I don't remember whether one could assume that whatever truth
value a Perl implementation used, it would be *consistent*. For
example, can one assume that the expression ((1 > 0) eq (1 > 0))
will always evaluate to true? Assuming that this is the case,
to code the test above one could write something like this

ok(foo() > 0, !!1, 'bad foo')

Are expressions such as !!1 and !1 (or !!2 and !3, etc.) the best
way in Perl to code true and false values in an implementation-independent
way?

Thanks,

kj
 
J

James Willmore

The if procedure Test::eek:k is given 3 arguments, it evaluates the first 2
arguments, tests to see if they are equal (using eq), and prints a
message involving the 3rd argument if they are not.

Supposing that we wanted a test that succeeded if foo() > 0, and having
the message upon failure contain the string "bad foo". One could use
something like ok(foo() > 0, 1, 'bad foo'), on the assumption that if
foo() > 0 was true it would evaluate to 1.

In this case, I'd just code ...
ok(foo(), 1, 'bad foo');

If foo() can only return '0' or '1', then a return value of '1' would
cause the test to pass. I don't see the point of going to any great
lengths to evaluate foo() it it only returns one of two values. It's
either true (1) or false (0).
I remember reading somewhere that it was bad form to assume any
particular value for a truth value in Perl, because the implementation
reserved the right to change this value.

Not sure where you got that. Logically, there is only one way to evaluate
truth. The issue of evaluating truth comes in when programmers don't
follow laws of logic in the code (such as DeMorgan's Law). *Some*
functions/methods don't follow a pre-conceived notion of "truth" (they
return "undef" upon failure versus "true" or "false"). Again, this is the
programmer, not the language :)

A subtle yet important example of what newbie programmers do is ignore
precedence. Consider the following code: ($foo && $bar && $fubar)

is different from
(($foo && $bar) && $fubar)

Both evaluate "truth" differently, but *may* arrive at the same
conclusion. If they arrive at the same conclusion once, then the newbie
will go and think that it's always this way, code something similar, then
ask "Why doesn't *this* work?". The answer is precedence :) According
to logic (subset of mathmatics), they are different statements of truth.
The issue in the above case is the programmer, not the language. The
language will do the logical thing.
But I don't remember whether one could assume that whatever truth value
a Perl implementation used, it would be *consistent*. For example, can
one assume that the expression ((1 > 0) eq (1 > 0)) will always evaluate
to true? Assuming that this is the case, to code the test above one
could write something like this

ok(foo() > 0, !!1, 'bad foo')

Are expressions such as !!1 and !1 (or !!2 and !3, etc.) the best way in
Perl to code true and false values in an implementation-independent way?

The example
((1 > 0) eq (1 > 0))

will *always* be true. It's a mathmatical (and logical :) ) truth.
However, why would one want to code
ok(foo() > 0, !!1, 'bad foo')

Unless this were an exercise in logic (meaning, one were evaluating truth
tables instead of crunching financial data), I wouldn't code like that.
It breaks the basic idea of "coding positive". I try to stay away from
code like

if(!$foo){
...
}

and instead write

unless($foo){
...
}

or code in such a way that evaluating $foo doesn't enter into the picture.
Not always practical or possible, but still a good direction to head :)
It's less code and there's no mistaking what you're trying to do. As
soon as you use some evaluation of "false" (!$foo), there's *always* going
to be someone who's not going to understand what you were trying to do.
It's subtle, I know. But since Perl has 'unless', I'm going to use it :)
Now, if this were another langauge (like COBOL), I'd still try to avoid
the idea of
using some "false" evaluation. It's easier to see "true" than "false" :)

The code you write is *not* for you, but the next person who is going to
maintain the code. If someone else can't follow what you wrote, be sure
that one year from now not even you will be able to follow what's going on
:)

Just my $0.02 :)

--
Jim

Copyright notice: all code written by the author in this post is
released under the GPL. http://www.gnu.org/licenses/gpl.txt
for more information.

a fortune quote ...
Office Automation, n.: The use of computers to improve
efficiency by removing anyone you would want to talk with over
coffee.
 
B

Bill

kj said:
The if procedure Test::eek:k is given 3 arguments, it evaluates the
first 2 arguments, tests to see if they are equal (using eq), and
prints a message involving the 3rd argument if they are not.

Supposing that we wanted a test that succeeded if foo() > 0, and
having the message upon failure contain the string "bad foo". One
could use something like ok(foo() > 0, 1, 'bad foo'), on the
assumption that if foo() > 0 was true it would evaluate to 1.

I remember reading somewhere that it was bad form to assume any
particular value for a truth value in Perl, because the implementation
reserved the right to change this value.

Yes, but for a given perl script run, it will not change the way they
are talking about. That would be something well defined by the time the
program is compiled. So---

If you are using the basic module Test.pm, the ok(arg1, arg2, arg3)
function type does a string eq type compare between arg1 and arg2 and
succeeds, I guess, if scalar arg1 eq scalar arg2. So don't worry about
what 'true' is. just do this:

ok(foo() > 0, 1 > 0, 'bad foo'); # will always be ok if foo() > 0

Also, for most complicated tests, consider Test::More since it allows
more varied constructs and so lets you avoid syntax convolutions like
that one.

-hth
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,901
Latest member
Noble71S45

Latest Threads

Top