01 May 1999 14:21:06 +0200
>>>>> "Tril" == Tril <firstname.lastname@example.org> writes:
Tril> I'm doing quite a bit of work in the background. Yeah, you
Tril> don't have to believe me. But go read my specs page, which is
Tril> very rough: http://tunes.org/~dem/tunes/Specifications.html.
Tril> Fare calls it "Design Notes" instead of specs. Whatever you
Tril> call it, he said it was right.
I read them, and I have a few thing to say :
o System Description
o Unique IDs
I mostly agree that unique ID are needed to identify and reference
objects, and that users of those references shouldn't know how they
are implemented. However, I have a problem with the following points :
"If the object disappears then your unique ID is
useless. And, if you allow anyone to access an object
if they know its ID, your system won't be very secure"
You say that the 1st issue can be tackled with a "two-way reference"
so that references can be invalidated when the object is
destroyed. Well why not. But what does it mean "to invalidate"
references to an object ? We could very well do a runtime checking and
see if the object referenced exists when we want to use it. And what
about garbage collection ?
You solve the security problem by saying that the client will not be
allowed to read the reference. By what can you do with it then ?
I think that the security issue is one aspect of system, and it
shouldn't interfere with the main functional aspect. Deciding who is
allowed to use an object should be independent of what the object can
do (it's functional aspect). This leads to a better reusability since
you can reuse the functional aspect without being forced to reuse a
security aspect that does not fit you needs.
o Functions and Types
I agree that one argument is all you need. But I think that specifying
a function only by its input and output type is a poor
specification. In fact, I think of typing as a special case of
pre/post conditions. If you allow any function to be used in the
pre/post conditions, they can be arbitrarily complex, and you can
fully specify what the function does (you don't need an implementation
since it is contained in the post condition). Let's take an example :
if you have a function `F' which takes an integer and returns an
integer, you don't know what it does. But if you say that the
pre-condition is that the argument is an integer, and that the
post-condition is that the result is such that `result = argument + 1'
you have a _full_ specification of F, and there's no need to implement
o Subtypes and Supertypes
Sets and subsets are one way to see things. But I believe that a
behavioral understanding of the subject can also be very
useful. Knowing that an object is part of a set of objects does not
tell much about it. What you usually want to know is what you can do
woth it, ie how it behaves. Have you read Liskov's papers about
behaviour and inheritance ? (I don"t have pointer, and my ISP is down,
sorry :-( ) It seems to me that the behavioral definition of types and
subtypes is the only one which makes sense.
o Generic Functions
Since this paragraph is based on your definition of types and I don't
agree with it, I don't agree with that one too :-) Especially when you
say that a generic function "is a function with no definition of its
own, but delegates to other functions". In fact this what all
functions do. But the dispatching algorithm vary. If you think about
it, all functions end up calling other functions (or themselves).
o Partial Evaluation
As I understand it, it's an optimisation technique. It may be
interesting, but I do not want to talk about that now.