I think we've got conflicting understandings of "trust" here.
One of the meanings might be characterized by the following quote:
"... it's just that in C++ and the like, you don't trust _anybody_,
and in CLOS you basically trust everybody. the practical result is
that thieves and bums use C++ and nice people use CLOS."
-- Erik Naggum
The basic point there is that the "Lisp approach," and, more
particularly, the "Common Lisp approach," is to build mechanisms that
are somewhat "trusting" in that if you _really_ wanted to, you could
write code that looks into the private details of objects and such.
In the "more paranoid" languages, the assumption is made that you
shouldn't be _able_ to have a mechanism to penetrate into the private
parts of function libraries. That sort of assumes that the
programmers are "thieves and bums" that would brazenly use such
mechanisms For Evil Purposes.
--
(concatenate 'string "cbbrowne" "@hex.net") <http://www.ntlug.org/~cbbrowne/>
"And 1.1.81 is officially BugFree(tm), so if you receive any bug
reports on it, you know they are just evil lies." -- Linus Torvalds
Does it look like a lot of work?
(defclass snake (legless-animal)
((length :initarg :length :type (real (0) *))
(poison :initarg :poison :type (member :a-joke :mostly-fatal))))
An :after method on shared-initialize can retrieve slot types (through
MOP) and check for compliance. You may additionally test relationship
between data (e.g., large snakes aren't poisonous), which you can do
with shared-initialize too. I don't know how you do that with static
type checking in ML, but the point is that type checking is only a small
part of the overall problem of validation.
Method definitions themselves serve as a (restricted) way of type
checking, for example
(reinitialize-instance 'e)
Error: No methods applicable for generic function
#<STANDARD-GENERIC-FUNCTION REINITIALIZE-INSTANCE> with args (E) of
classes (SYMBOL)
Manifest typing is also necessary when your module works with a
collection or stream of heterogenous objects.
Robert