On Mon, 13 Oct 1997 10:22:34 -0700,
Kent M Pitman <······@world.std.com> wrote in comp.lang.lisp:
>Vassil Nikolov <········@math.acad.bg> writes:
>
>> Is there a better way to test if something is a type
>> specifier than doing
>> (ignore-errors (subtypep type-specifier-maybe 't))
... text omitted...
>One issue, though, is that CL permits forward references...
[it is permitted to compile, but not to evaluate, (sub)expressions
containing undefined type specifiers]
>So, for example, a macro would be incorrect in doing
>something like
>
> (defmacro g (x)
> (check-type x type-specifier)
> ...)
>
>in your proposed definition of the type specifier. At bare
>minimum, it would need an env arg, and in the presence of
>forward references, that would still not be enough. It would
>lead to lots of program errors.
The above is indeed clearly incorrect because CHECK-TYPE requires
its type specifier argument to be known at compile time (it
is not evaluated). Functions like TYPEP and SUBTYPEP, however,
are not bound by such a requirement.
So, with or without forward references, there can be a time
during the execution of a program, i.e. in the presence
of a dynamic context in addition to the lexical one,
when a dynamically computed type specifier may be processed.
I suppose that it is reasonable to say that a function like
TYPEP can detect, *in the current lexical _and_ dynamic
context*, if it is given a valid^1 type specifier or not.
My idea is for (the hypothetical) TYPE-SPECIFIER-P to
perform precisely this detection and no more. Or,
conversely, shall we adopt the principle that
although new type specifiers can be constructed dynamically
in Lisp, type specifiers can be `fully' recognised
as such no later than compile time. In other words,
a valid Lisp program which processes a dynamically
computed type specifiers simply has no standard
way of dynamically checking if they are valid
(e.g. if it OK to pass them to TYPEP or SUBTYPEP).
_______________
^1 If it is valid, there would be a `yes or no' answer;
it is an error if it isn't. Unfortunately I don't
remember, and while I am writing this I have no way of
checking, if an error must be _signalled_ in such a
case; I suspect not, i.e. the consequences are merely
undefined.
>As strange as it sounds,
> (check-type x (or symbol cons class) "a type specifier")
>is going to be more likely to be right in a lot of places.
Quite so; I was looking for something more discriminative.
... text omitted...
>... suppose you know that FOO is undefined,
>is (SATISFIES FOO) a type specifier or not?
My own weird philosophical view is that in this case
(SATISFIES FOO) _is_ a type specifier which is undefined.
Or should I say `a potential type specifier'? In other
words, which parallel is better: to unbound variables
or to potential numbers? We can in fact consider a
much simpler case: a single symbol, FOO, which is not
associated with any DEFTYPE or DEFSTRUCT definition
nor does it name a class. Which should we prefer:
to say that (A) it is undefined as a type specifier,
or (B) it is a potential type specifier?
... text omitted...
Best regards,
Vassil.
Vassil Nikolov <········@bgearn.acad.bg> (+359-2) 713-3813
Department of Information Research
Institute of Mathematics and Informatics fax: (+359-2) 9713649
Acad. G. Bonchev, block 8, Sofia 1113, Bulgaria
In article <··············@math.acad.bg> "Vassil Nikolov" <········@math.acad.bg> writes:
> with or without forward references, there can be a time
> during the execution of a program, i.e. in the presence
> of a dynamic context in addition to the lexical one,
> when a dynamically computed type specifier may be processed.
> I suppose that it is reasonable to say that a function like
> TYPEP can detect, *in the current lexical _and_ dynamic
> context*, if it is given a valid^1 type specifier or not.
You misunderstood the nature of my argument. It wasn't to say that
the thing you described is semantically ill-formed. It was, rather,
to observe that part of the burden of a language designer is not only
to provide good functionality, but to live with the improper use of
that functionality (and to consider how to avoid such improper uses
the next time around). I was merely noting that TYPE-SPECIFIER-P
would be substantially abused because people would tend to write code
like:
(defmacro my-check-type (var type string &environment env)
(unless (type-specifier-p type env) (error ...))
...)
You seem to agree with me that it's improper for them to write code
like that, so I won't belabor that point, but rather will try to
reiterate my point which is that it LOOKS to the naive programmer (who
often isn't facile with the various "times" of evaluation) that he's
just doing "the good thing" of checking the type. After all, here is
a macro that's supposed to get a type specifier arg--why would that
not be a good thing to test? It's compile time, so speed doesn't
matter. And isn't checking better than not checking? Answer: no,
secretly type specifiers are understood only by Kent and Vassil and a
privileged club of 17 other people to mean "type specifiers at time T"
and we secretly know that this is not a good value of T to be testing.
But this is a subtlety lost on most programmers.
This is an excellent example of my frequently claim that languages are
ecologies and you can't just decide that an operator is "good".
Things can only be "good in a context" (sort of a meta-invocation of
the same problem I was describing above). In this case, you have a
language that tries to keep you from caring about execution order, and
you're introducing an operator that's highly sensitive to execution
order. It's not that what you asked for is not well-defined, it's
just that it's what is called under American law "an attractive
nuissance"... like a store window that flashes a bright sign saying
"come look at me" in the middle of the night when the store is closed
and then the only thing the person finds when he comes to the sign is
a big sheet of ice (because it's night and cold and no one is there to
clean the sidewalk)... the store owner says, "what did you expect? it
was night. you have to be careful" but the courts say "no, you flashed
the pretty light and attracted the person to this hazardous area--you
share the responsibility for the misuse".
APPEND is the prototypical attractive nuissance in Lisp. There are
legitimate circumstances its use, which is why it is present in the
language. But most uses are improper and anyone looking for
performance bottlenecks will immediately look for calls to APPEND. We
include the operator because there are simple cases where it's
well-defined and not a problem, but we do so at the terrible price of
knowing that it will lead to horrible inefficiency in the hands of
those who don't know what they are doing.