Discussion:
Style issue about predicates
Daniel Weinreb
2011-01-14 16:42:16 UTC
Permalink
If you have a function that is a predicate, in the sense that
the function's contract says that its value should be interpreted
as being either false or true, do you think it's better to code
it so that it always returns "t" for the true case?

Since Common Lisp is quite clear that when a value
is being considered in the context of being true/false,
nil means false and everything else means true.
So from a language point of view, even considering
the "intent" of the definition and not just the spec,
there is no need to return t.

Furthermore, the contract of the function should
make it clear that the returned value is an a
true/false context. This should be in the doc
string, or at least in a comment, and the function
name should end in "p" (or always "-p" but let's
please not get into that in this email thread).
So the caller should know.

All that said, it's possible that a programmer will
fail to heed the contract, simply look at the code,
and take advantage of the returned value in
more than true/false context. If you want to prevent
that, you can do something like:

(defun ...
...
(when (fn1 arg2 arg2)
t))

It seems that it might depend on the circumstance: how likely
do you think it is that a programmer would commit such
a mistake? The more potentially valuable the returned value
is, the more likely. On the other hand, if it's so valuable,
maybe you should actually make that part of the contract
rather than making the function have the contract of
a predicate.

Is this good, bad, don't care, depends on the circumstance?

-- Dan
Edi Weitz
2011-01-14 16:59:52 UTC
Permalink
There are lots of functions in the standard which are predicates in
that they return generalized booleans but on the other hand return
something "useful" if the result is not NIL, e.g. MEMBER or STRING<.
I think this is good practice, i.e. return something other than T in
case this might make more sense. Of course, this should then be
documented in the predicate's contract and thus should be OK to use by
the caller.
Post by Daniel Weinreb
If you have a function that is a predicate, in the sense that
the function's contract says that its value should be interpreted
as being either false or true, do you think it's better to code
it so that it always returns "t" for the true case?
Since Common Lisp is quite clear that when a value
is being considered in the context of being true/false,
nil means false and everything else means true.
So from a language point of view, even considering
the "intent" of the definition and not just the spec,
there is no need to return t.
Furthermore, the contract of the function should
make it clear that the returned value is an a
true/false context.  This should be in the doc
string, or at least in a comment, and the function
name should end in "p" (or always "-p" but let's
please not get into that in this email thread).
So the caller should know.
All that said, it's possible that a programmer will
fail to heed the contract, simply look at the code,
and take advantage of the returned value in
more than true/false context.  If you want to prevent
(defun ...
...
(when (fn1 arg2 arg2)
 t))
It seems that it might depend on the circumstance: how likely
do you think it is that a programmer would commit such
a mistake?  The more potentially valuable the returned value
is, the more likely.  On the other hand, if it's so valuable,
maybe you should actually make that part of the contract
rather than making the function have the contract of
a predicate.
Is this good, bad, don't care, depends on the circumstance?
-- Dan
_______________________________________________
pro mailing list
http://common-lisp.net/cgi-bin/mailman/listinfo/pro
Nick Levine
2011-01-14 17:03:52 UTC
Permalink
From: Edi Weitz <edi-***@public.gmane.org>
Date: Fri, 14 Jan 2011 17:59:52 +0100
Cc: Sergey Vasilyev <sergey-eC8/***@public.gmane.org>,
Common Lisp Professionals <pro-***@public.gmane.org>

There are lots of functions in the standard which are predicates in
that they return generalized booleans but on the other hand return
something "useful" if the result is not NIL, e.g. MEMBER or
STRING<.

And some of them might also end in -p

(digit-char-p)

-nick
Ben Hyde
2011-01-14 17:05:56 UTC
Permalink
Post by Daniel Weinreb
If you have a function that is a predicate, in the sense that
the function's contract says that its value should be interpreted
as being either false or true, do you think it's better to code
it so that it always returns "t" for the true case?
I am distracted by the need to write:

(defun truthy (x) (not (not x)))

or if you's is the kind of organization that builds a development v.s.
a production version...

(defmacro truthy (x) #+dev `(not (not ,x)) #-dev `,x)

It would be nice to have a code base that is more truthy.
Mark H. David
2011-01-14 17:00:27 UTC
Permalink
No, it should just return "true" (non-nil). It shouldn't guarantee T as a value, nor any particular "true" value.

It's wrong for the programmer using a predicate to rely on the "true" value being any particular value, including T.

Therefore, doing the (when ... t) thing just makes it return one particular true value (T) that the programmer should not rely upon anyhow.

-Mark
Post by Daniel Weinreb
If you have a function that is a predicate, in the sense that
the function's contract says that its value should be interpreted
as being either false or true, do you think it's better to code
it so that it always returns "t" for the true case?
Since Common Lisp is quite clear that when a value
is being considered in the context of being true/false,
nil means false and everything else means true.
So from a language point of view, even considering
the "intent" of the definition and not just the spec,
there is no need to return t.
Furthermore, the contract of the function should
make it clear that the returned value is an a
true/false context. This should be in the doc
string, or at least in a comment, and the function
name should end in "p" (or always "-p" but let's
please not get into that in this email thread).
So the caller should know.
All that said, it's possible that a programmer will
fail to heed the contract, simply look at the code,
and take advantage of the returned value in
more than true/false context. If you want to prevent
(defun ...
...
(when (fn1 arg2 arg2)
t))
It seems that it might depend on the circumstance: how likely
do you think it is that a programmer would commit such
a mistake? The more potentially valuable the returned value
is, the more likely. On the other hand, if it's so valuable,
maybe you should actually make that part of the contract
rather than making the function have the contract of
a predicate.
Is this good, bad, don't care, depends on the circumstance?
-- Dan
_______________________________________________
pro mailing list
http://common-lisp.net/cgi-bin/mailman/listinfo/pro
Scott L. Burson
2011-01-14 17:23:34 UTC
Permalink
Post by Daniel Weinreb
If you have a function that is a predicate, in the sense that
the function's contract says that its value should be interpreted
as being either false or true, do you think it's better to code
it so that it always returns "t" for the true case?
I've never bothered.

Of course I'm also one of these people who routinely use AND and OR to
return non-boolean values, which apparently a lot of people dislike
(it's specifically contravened in Peter Norvig's style guide, for
instance).

BTW I prefer the trailing question mark convention over "-p". Scheme
uses the question mark, but I'm not sure the convention originated
there -- I think it may actually have started in the InterLisp
community. Does anyone know?

-- Scott
Luke Crook
2011-01-14 20:42:17 UTC
Permalink
Post by Daniel Weinreb
If you have a function that is a predicate, in the sense that
the function's contract says that its value should be interpreted
as being either false or true, do you think it's better to code
it so that it always returns "t" for the true case?
I use '-p' and '?' depending on the function name aesthetics (generally not both
in the same function name). These return whatever object is being tested, for
example physics-hook-p will return a function or NIL otherwise.

How about defining defsetf for predicates?

-Luke
Bob Kerns
2011-01-15 03:49:28 UTC
Permalink
Dan, my firm-but-not-rabid opinion on this has been formed from decades of
tracking down portability bugs, irreproducible bugs, etc.

Return 't'. Try to get the contract tightened up to specify t.

But so long as the contract is loose, in testing it can be useful to try to
inject defects by returning other values.

For any one instance of this, the odds of there being a bug based on the
return value is low. But given how many functions return boolean values, the
odds of none of the calls to them having a bug aren't so good. Making
everything return 't' as a matter of standard practice has the potential to
eliminate quite a number of bugs (in the sense of bad behavior, rather than
in the sense of incorrect coding).

It's not just Lisp that has this problem. I've seen quite a number of C/C++
bugs where code erroneously depended on a return value of 1 or -1 or
odd/even or positive/negative when it should have been zero/non-zero.

A similar area is when algorithms are sensitive to the order of traversal of
hash tables. Java supplies LinkedHashTable and LinkedHashSet, which is one
approach to removing this variability.

In both cases, the real issue isn't so much that there can be bugs. It is
that the bugs that can result, have the potential to be very hard to
reproduce, test for, and eliminate. An API contract that doesn't leave this
sort of wiggle room makes for much better testability.

Of course, if everyone follows this rule, there's no need for:
(when (fn1 arg2 arg2)
t)

because fn1 would have returned t or nil -- unless you have an actual
mismatch/conversion of contract. In that case, I argue that it is best to
actually capture that intent in the code, as well as all the benefits
above. But perhaps it should be written:
(not (eq (fn1 arg2 arg2) null))
and reserve when for actual control-flow matters, rather than boolean
operations.


Date: Fri, 14 Jan 2011 11:42:16 -0500
From: Daniel Weinreb <dlw-eC8/***@public.gmane.org>
Subject: [pro] Style issue about predicates

If you have a function that is a predicate, in the sense that
the function's contract says that its value should be interpreted
as being either false or true, do you think it's better to code
it so that it always returns "t" for the true case?

Since Common Lisp is quite clear that when a value
is being considered in the context of being true/false,
nil means false and everything else means true.
So from a language point of view, even considering
the "intent" of the definition and not just the spec,
there is no need to return t.

Furthermore, the contract of the function should
make it clear that the returned value is an a
true/false context. This should be in the doc
string, or at least in a comment, and the function
name should end in "p" (or always "-p" but let's
please not get into that in this email thread).
So the caller should know.

All that said, it's possible that a programmer will
fail to heed the contract, simply look at the code,
and take advantage of the returned value in
more than true/false context. If you want to prevent
that, you can do something like:

(defun ...
...
(when (fn1 arg2 arg2)
t))

It seems that it might depend on the circumstance: how likely
do you think it is that a programmer would commit such
a mistake? The more potentially valuable the returned value
is, the more likely. On the other hand, if it's so valuable,
maybe you should actually make that part of the contract
rather than making the function have the contract of
a predicate.

Is this good, bad, don't care, depends on the circumstance?

-- Dan
Svante Carl v. Erichsen
2011-01-15 14:23:48 UTC
Permalink
Hi!

I would not like such a rule in a style guide, for fear of religious
followers. My view is: yes, tighten the contract, but no, it needs
not (but may) specify exactly t. If something useful can be returned,
why throw it away?

Best wishes

Svante
Post by Bob Kerns
Return 't'. Try to get the contract tightened up to specify t.
But so long as the contract is loose, in testing it can be useful to try to
inject defects by returning other values.
For any one instance of this, the odds of there being a bug based on the
return value is low. But given how many functions return boolean values, the
odds of none of the calls to them having a bug aren't so good. Making
everything return 't' as a matter of standard practice has the potential to
eliminate quite a number of bugs (in the sense of bad behavior, rather than
in the sense of incorrect coding).
Bob Kerns
2011-01-15 18:18:05 UTC
Permalink
Just to clarify my earlier stance: I agree -- if there's something
well-defined and more useful than T to return, return that. It's the
'null/non-null' contracts that are problematic.

The extra wiggle-room here offers no utility at all. It does allow for one
branch of an implementation to avoid a constant load, or in some cases a
test/branch and load. In this day and age, I do not find small constant bits
of CPU compelling, in contrast to matters that affect reliability of
large-scale software, when coded by real-world teams of programmers.

----------------
Date: Fri, 14 Jan 2011 17:59:52 +0100
From: Edi Weitz <edi-***@public.gmane.org>
Subject: Re: [pro] Style issue about predicates

There are lots of functions in the standard which are predicates in
that they return generalized booleans but on the other hand return
something "useful" if the result is not NIL, e.g. MEMBER or STRING<.
I think this is good practice, i.e. return something other than T in
case this might make more sense. Of course, this should then be
documented in the predicate's contract and thus should be OK to use by
the caller.
Bob Kerns
2011-01-15 19:21:17 UTC
Permalink
Agreed. As I indicated later, throwing away useful information wasn't my
intent -- having a tight, well-defined contract was. T serves that purpose,
but other values may also serve it and add utility at the same time.

The WORST case, in my mind, is to return something useful, but leave the
contract as "non-null". This encourages programmers, who may or may not have
observed the contract wording, to experimentally observe the actual
behavior, and depend on it.

It's probably even more likely in Lisp than in most languages, because it's
so easy to type a test case into a read-eval-print loop.

I am not generally dogmatic that all aspects of all behavior need to be
tightly specified. For example, there can be substantial performance
benefits to leaving traversal/iteration orders unspecified, or there can be
substantial benefit from implementation freedom, or it can be completely
impractical to write a full specification.

But return values, especially boolean return values, are well worth
consistently specifying tightly. And I think there's little danger of a
religion arising based on it -- and it'd be a relatively harmless one even
so.

-----------

Date: Sat, 15 Jan 2011 15:23:48 +0100
From: "Svante Carl v. Erichsen" <Svante.v.Erichsen-S0/***@public.gmane.org>
Subject: Re: [pro] Style issue about predicates
Hi!

I would not like such a rule in a style guide, for fear of religious
followers. My view is: yes, tighten the contract, but no, it needs
not (but may) specify exactly t. If something useful can be returned,
why throw it away?
Tobias C Rittweiler
2011-01-16 10:41:39 UTC
Permalink
Post by Daniel Weinreb
If you have a function that is a predicate, in the sense that
the function's contract says that its value should be interpreted
as being either false or true, do you think it's better to code
it so that it always returns "t" for the true case?
Since Common Lisp is quite clear that when a value
is being considered in the context of being true/false,
nil means false and everything else means true.
So from a language point of view, even considering
the "intent" of the definition and not just the spec,
there is no need to return t.
Furthermore, the contract of the function should
make it clear that the returned value is an a
true/false context. This should be in the doc
string, or at least in a comment, and the function
name should end in "p" (or always "-p" but let's
please not get into that in this email thread).
So the caller should know.
All that said, it's possible that a programmer will
fail to heed the contract, simply look at the code,
and take advantage of the returned value in
more than true/false context. If you want to prevent
(defun ...
...
(when (fn1 arg2 arg2)
t))
It seems that it might depend on the circumstance: how likely
do you think it is that a programmer would commit such
a mistake? The more potentially valuable the returned value
is, the more likely. On the other hand, if it's so valuable,
maybe you should actually make that part of the contract
rather than making the function have the contract of
a predicate.
Is this good, bad, don't care, depends on the circumstance?
-- Dan
I think it's good style to make predicates return T (except
for the rare case Edi cited where the return value could
also legitimately be made sense of differently.)

Returning another value that the user might see
when playing at the REPL seems like leaking internal
decomposition to me.

I also prefer to use (AND (FOO ...) T) rather than
WHEN in that case because WHEN is a control-flow
construct but this case is about data normalization,
and thus I consider AND more appropriate.

-T.
Ala'a Mohammad
2011-01-16 18:23:32 UTC
Permalink
......................., do you think it's better to code
it so that it always returns "t" for the true case?
my current practice is to use other-than-nil as truth value in
predicates. Even if current application needs t or nil only. this will
help avoid breaking older code (which did not assume 't' is the only
truth) in case I find a way for returning a useful other-than-nil
value in future. OTOH, I think this (using a generalized-boolean
rather than boolean) will mesh well with CL style (most of it).

In case of 'nil' as a useful value, I'll return multiple values
similar to gethash.

also I try (most of the time if possible) to adhere to the definitions
in the glossary of CLHS. in this case it defines a predicate as a
function returning generalized-boolean as its first value. (I do this
in part so that CLHS wil act as a part in documenting the terms used
in my own documentation like doc strings and others, in other words
having a common glossary to use)
Furthermore, the contract of the function should
make it clear that the returned value is an a
true/false context.
I'll use the followings (from CLHS glossary) in documenting the return value(s)
Boolean for t and nil symbols
Generalized Boolean for nil and others-are-true
(defun ...
...
(when (fn1 arg2 arg2)
t))
or use

(defun truep (object)
(not (not object)) ;; 'not' is specified to return either nil or t only

(defun ...
....
....
(truep (predic1 arg1 arg2))

;; both name and implementation on comp.lang.lisp from Kent (~ around
13 years ago)

Regards,

Ala'a Mohammad.

Loading...