Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

:test :test-not validation

18 views
Skip to first unread message

Pascal J. Bourguignon

unread,
Jan 1, 2019, 8:52:27 AM1/1/19
to
Happy New Year!


Reading CLHS, I synthetize those different cases for passing :test and/or
:test-not arguments to the standard CL functions that take them.

specified or result: :test/:test-not
unspecified error or test arguments
------------ -------------- --------------------------
(:specified (test foo) (:test foo))
(:specified (test-not foo) (:test-not foo))
(:specified type-error (:test nil))
(:specified type-error (:test-not nil))
------------ -------------- --------------------------
(:unspecified (test foo) (:test foo :test-not nil))
(:unspecified (test-not foo) (:test nil :test-not foo))
(:unspecified error (:test foo :test-not bar))
(:unspecified error (:test nil :test-not nil))
------------ -------------- --------------------------

Here are the results:
https://gist.github.com/informatimago/4afdb7021c69a049d15672055e2512c8

Basically, all the main implementations give the same result (only test
for CL:FIND), which differs from my reading of the CLHS:

((:SPECIFIED :SUCCESS 102)
(:SPECIFIED :SUCCESS 2)
(:SPECIFIED :SUCCESS 1)
(:SPECIFIED :FAILURE 102) ; *
(:SPECIFIED :FAILURE 102) ; *
(:UNSPECIFIED :SUCCESS 2)
(:UNSPECIFIED :SUCCESS 1)
(:UNSPECIFIED :SUCCESS #<SIMPLE-ERROR "can't specify both :TEST and :TEST-NOT" {10027425D3}>)
(:UNSPECIFIED :FAILURE 102))

The cases where we pass NIL to :test or :test-not, which is specified to
signal a type-error, behaves as if they weren't passed.

17.2.1 says that:

"A :test argument, if supplied to F, is a designator for a function
of two arguments, …"

NIL is not a designator for a function of two arguments, therefore
it should be a type-error.


--
__Pascal J. Bourguignon__
http://www.informatimago.com

Madhu

unread,
Jan 1, 2019, 12:01:43 PM1/1/19
to
* "Pascal J. Bourguignon" <m28t04m...@despina.home> :
Wrote on Tue, 01 Jan 2019 14:52:22 +0100:

> The cases where we pass NIL to :test or :test-not, which is specified to
> signal a type-error, behaves as if they weren't passed.

You should be glad for that!

> 17.2.1 says that:
>
> "A :test argument, if supplied to F, is a designator for a function
> of two arguments, ..."
>
> NIL is not a designator for a function of two arguments, therefore
> it should be a type-error.

1. "if Non-NIL" is better phrasing than "if supplied" in this case;
supplying NIL means that no TEST is supplied.

The spec is usually explicit in specifying NIL when prompting for an
optional or keyword argument to be supplied. but there is one other
place I remember from the top of my head where there is a problem:

"encode-universal-time converts a time from Decoded Time format
to a universal time. If time-zone is supplied, no adjustment for
daylight savings time is performed."

This means that one has to call this function very carefully because of
perverse implementations:

(if (null time-zone)
(encode-universal-time second minute hour date month year)
(encode-universal-time second minute hour date month year
time-zone))

2. On the question of TEST and TEST-NOT here is the docstring for
INSERT-ORDERED from my cmucl-init (I have probably posted that here
before), where I use found a use for specifying both TEST and TEST-NOT:

(defun insert-ordered (item list &optional (predicate #'<)
&key key test test-not)
"Insert ITEM in LIST. may modify LIST. LIST is assumed to be
sorted by PREDICATE. If TEST (or TEST-NOT) is non-NIL, it is used
to determine if ITEM is present (or absent) in LIST, in which
case it is not inserted. KEY if non-NIL is applied to both ITEM
and elements of LIST before comparing them. However, unlike
section 17.2.1 of the spec, if both TEST and TEST-NOT are NIL, no
test is made.")

;; TEST could be specified to take precedence if both are supplied.

Pascal J. Bourguignon

unread,
Jan 1, 2019, 12:42:22 PM1/1/19
to
Madhu <eno...@meer.net> writes:

> * "Pascal J. Bourguignon" <m28t04m...@despina.home> :
> Wrote on Tue, 01 Jan 2019 14:52:22 +0100:
>
>> The cases where we pass NIL to :test or :test-not, which is specified to
>> signal a type-error, behaves as if they weren't passed.
>
> You should be glad for that!
>
>> 17.2.1 says that:
>>
>> "A :test argument, if supplied to F, is a designator for a function
>> of two arguments, ..."
>>
>> NIL is not a designator for a function of two arguments, therefore
>> it should be a type-error.
>
> 1. "if Non-NIL" is better phrasing than "if supplied" in this case;
> supplying NIL means that no TEST is supplied.

Not in the context of &key or &optional arguments, where an explicit
suppliedp flag can be obtained.

And notably, some functions are defined with different behavior for not
supplied and nil supplied.

> 2. On the question of TEST and TEST-NOT here is the docstring for
> INSERT-ORDERED from my cmucl-init (I have probably posted that here
> before), where I use found a use for specifying both TEST and TEST-NOT:

Of course, there are two questions here:

1- what does clhs specifies for :test/:test-not
2- what should new functions check and do for their :test/:test-not.

We want the later to be consistent with the former.
0 new messages