Article View: comp.lang.misc
Article #3138Re: CHALLENGE: typing and reusability (was: Re: blip)
From: urs hoelzle
Date: Wed, 27 Mar 1991 04:02
Date: Wed, 27 Mar 1991 04:02
93 lines
4994 bytes
4994 bytes
In <1991Mar26.005805.1914@kodak.kodak.com> cok@islsun.Kodak.COM (David Cok)
writes:
> However, I do prefer static typing where it works and am interested in
^^^^^^^^^^^^^^
> discovering how to make it work better. In any case Hoelzle's programming
Sure... I guess we just disagree what "works" means :-)
But now to the technical points: your code example is nice, but (as
you mention yourself) it doesn't solve the problem because of a typing
snag, and that was exactly my point. Furthermore, it has two other problems:
1) It assumes that you have source code access to A and B. You write that
> If a programmer did not
> have source code access to A and B, one could still create classes MyA (MyB)
> which inherited from both A (B) and FooDisplayable. The programmer would have
> to use MyA and MyB everywhere instead of A and B (at least where things might
> be put on the list) and A and B would have had to declare display and foo
> virtual.
This doesn't work as soon as you also have Lists of A (or other
classes parametrized by A) in existing modules, because List[MyA] is
not a subtype of List[A]. This is a result of the contravariance rule
(see e.g. "A Proposal for Making Eiffel Type-Safe" by W. Cook,
ECOOP'89; "Introduction to Trellis/Owl", OOPSLA'86 [I might have
gotten the years slightly wrong]).
The problem isn't really with contravariance, but with the way it is
applied: type-checkers don't only check the validity of your program,
but also the validity of *all possible variations*:
someProc(List[FooDisplayable]) is illegal because someProc *could* use
List::insert to insert a Fooable instead of a FooDisplayable, which would
violate the type assertion for the list.
HOWEVER, the existing version of someProc *does not* use any "dangerous"
List operation such as insert() and is perfectly safe. But today's
type checkers are unable to recognize this because they still live
in a world of batch-style compilation and are prohibited from looking
at the *actual* use of objects. Therefore, they have to use worst-case
assumptions about the *potential* uses and unnecessarily restrict the
programmer.
[For Eiffel programmers: before you agree with me, let me say that what
Eiffel does is *not* what I propose here. Eiffel's "solution" to the
problem is, IMHO, totally wrong. :-)]
> As the original poster pointed out, this will not give any runtime message
> errors in a dynamically typed system. However, I'd maintain that it is a bad
> use of dynamic typing. The only thing that prevents errors is the semantic
> knowledge that someProc only does foo and not anything else that Footype allows.
> If someProc were modified later by someone who did not know that it was applied
> to a FooDisplayable list, errors would result.
Sure, type errors would result in a statically-typed language, and
run-time errors in a dynamically-typed language. There's no problem
with that: if your change transforms a type-correct (in my sense, not
C++'s) program into an unsafe program, you get an error.
2) You need a new type of iterator for every type of message you want
to send to the list.
This is actually orthogonal to the issue of dynamic vs. static typing
since it is about closures. In Self/Smalltalk, you define one
iterator which takes a block. The block is the called by the
iterator, once for every element, with the element as an argument.
Thus you can do
list do: [ | :elem | elem foo ] "original example"
list do: [ | :elem | elem bas: 15]
or (assuming that prev is a local in the caller of do:)
prev: nil.
list do: [ | :elem | elem baz: prev. prev: elem ]
You could introduce closures to C++ et al, but it's interesting to
observe that no statically-typed language has them, while many
dynamically-typed languages do. You could also simulate this in C++
with function pointers, but you have to "invent" a procedure for every
(trivial) block... reminds me of COBOL where you were forced to write
your loop bodys as separate sections ;-)
-Urs
PS:
> >>>>> Compiling takes too long. I want runtime syntax checking! <<<<<
Hey, you can have this in Self - almost every string of characters
with balanced parentheses is a legal Self expression. :-)
Technical Details
Message-ID:
<1991Mar27.040253.17343@leland.Stanford.EDU>Path:
arc1-ca.pugleaf.net!utzoo!utgpu!news-server.csri.toronto.edu!cs.utexas.edu!usc!snorkelwacker.mit.edu!stanford.edu!leland.Stanford.EDU!elaine13.Stanford.EDU!hoelzleReferences:
<jls.669591628@rutabaga> <1991Mar22.210725.29448@neon.Stanford.EDU> <1991Mar26.005805.1914@kodak.kodak.com>Show Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!utzoo!utgpu!news-server.csri.toronto.edu!cs.utexas.edu!usc!snorkelwacker.mit.edu!stanford.edu!leland.Stanford.EDU!elaine13.Stanford.EDU!hoelzle From: hoelzle@elaine13.Stanford.EDU (urs hoelzle) Newsgroups: comp.lang.misc,comp.object,comp.lang.eiffel Subject: Re: CHALLENGE: typing and reusability (was: Re: blip) Message-ID: <1991Mar27.040253.17343@leland.Stanford.EDU> Date: 27 Mar 91 04:02:53 GMT References: <jls.669591628@rutabaga> <1991Mar22.210725.29448@neon.Stanford.EDU> <1991Mar26.005805.1914@kodak.kodak.com> Sender: news@leland.Stanford.EDU (Mr News) Organization: Stanford University - AIR Lines: 93