Re: object system...
- From: "cr88192" <cr88192@xxxxxxxxxxx>
- Date: Mon, 12 Jan 2009 11:49:12 +1000
"Dmitry A. Kazakov" <mailbox@xxxxxxxxxxxxxxxxx> wrote in message
news:5i8m2lc22zhl$.kwap40jboi79.dlg@xxxxxxxxxxxxx
On Sun, 11 Jan 2009 16:11:35 +1000, cr88192 wrote:
"Dmitry A. Kazakov" <mailbox@xxxxxxxxxxxxxxxxx> wrote in message
news:749vn6hmsyca$.7n12zq0r7svb.dlg@xxxxxxxxxxxxx
Lieberman's stuff is all wrong to me. "Delegation between object" sounds
conceptually messy.
given what all else is said, this does not surprise me...
the way it all works is actually quite "elegant" in and of itself (since
the
use of delegation and cloning can eliminate both the need for classes,
and
also the need for inheritence).
Yep, spaghetti in short. This is like gotos eliminate any need in
if-then-else. The problem is that this is an extremely low-level stuff. If
you don't have types, you are unable to judge about sets of objects in
terms of their commonality. That is huge jump backwards into prehistoric
times of computing...
[... consequences of going untyped ...]
both goto and untyped constructs have their place, it is just more common
that we formalize and gloss over them, thus providing more pleasing
alternatives.
for example, few are likely to doubt that a 'for' or 'while' loop is
preferable to an 'if-goto' construction, none the less, goto and labels are
the more general construct, and if-goto can be considered more as syntactic
sugar.
none the less, it is a lot easier to optimize code with loops or
if-then-else, than code written via gotos (optimizing if a given branch is
always true or false, unrolling loops, ...), however it is also the case
that nearly every compiler I am aware of converts over to the use of gotos
fairly early on (and I am not aware of any IL which uses high-level control
flow rather than labels and gotos/jumps...).
the situation is not the same, however, in the case of class/instance vs
prototypes, where although prototyping is conceptually the more general
construct, as a general rule it is not practical to compile from C/I to
prototypes (due in large part to performance and overhead issues, ...).
instead, it is much more common for C/I systems to reduce down to raw globs
of memory, which is more or less what mine does (actually, it is a struct
containing a pointer to a raw glob of memory, a class pointer, class
version, ...).
if any prototype features are used, additional memory is allocated for a
slots-array and an additional data chunk (as well as a secondary "prototype
header"). sadly, this costs the space of a pointer being held in the object
header (the alternative would have been to use hidden fields in the main
object, but this raised other issues, and so I decided that storing the
pointer in the header for all objects was the cheaper of the options...).
so: object header currently takes 5 pointers (or 20 bytes on x86, 40 on
x86-64).
the garbage collector has an additional overhead of 16 bytes (the main
object header), and the object is forced up to a multiple of 16 bytes.
thus: object header is 48 bytes on x86, 64 on x86-64.
then, it is similar for the payload (16+size padded up to 16, or
(((16+size)+15)&(~15)) in C terms...).
class Foo {
int x, y;
}
48 bytes header, 32 payload, 80 bytes total (however, the overhead of all
this will decrease as the object size increases).
dynamically adding a slot (or using delegation, ...) will drastically
increase this though:
48 bytes, P-OO header;
32 bytes, dynamic slot list;
32 bytes, dynamic slot payload;
32 bytes, dynamic method list;
32 bytes, dynamic method payload.
176 additional bytes, 256 bytes total (x86).
P-OO by itself will cost 224 bytes (no C/I payload, NULL class pointer,
....).
note: there is currently no explicit delegates list (delegates currently
exist as special slots), but a delegates list would push the P-OO header to
64 bytes (but may help some with P-OO performance as one need no longer look
for delegate slots, although the central hash tables will largely eliminate
this cost anyways...).
so, yes, although one can use prototype features, they should not, as the
additional overhead costs are high.
also, note that the memory overhead of storing a class is not exactly small
either (a class likely by far dwarfs the instance), but this is OK as the
number of classes is likely to be small vs the instances (in total, each
class is likely to take several KiB of memory...)
....
As for Kay, this is a different case. He talks about
transaction-oriented
approach to object updates. This is quite concrete and I agree that this
is a very important issue. But I have some reservations:
1. This is not an alternative (it is rather a meta layer)
2. This cannot be reduced to just one object. I.e. it is not literally
OO,
because it involves many objects. He introduces "world," but this is too
sloppy in my eyes. I would expect some *object* corresponding to the
"world."
In short a bit more meat is required to consider it seriously.
Especially
because the theory of OO itself is quite shaky, while it [obviously]
should serve as a basis for transactions.
yeah...
I guess the idea though is that usually one thinks much more in terms of
an
"object world" or "object environment" than in terms of individual
objects
in isolation...
Yes, but the problem is to formalize the object environment in some way.
And what are the items in the environment? Other objects! What about the
environments of those. How these environments interact? Looks like a mess.
OO was introduced to sort out this mess by placing the volatile stuff
(states) into a thing called object. Either Kay wish to make
object-oriented into environment-oriented where "environment" is another
word for "object", or else, is it what?
if one needs to formalize the system, they are likely to revert back to a
class/instance mindset, or possibly some other formalism, such as a
node-graph, ...
Interface deals with the type, not an object of. As any base type it
adds
nothing being a separate type from the result. Inheritance is an
algebraic
operation that takes some arguments, like interface, and produces the
result, the type or interface.
we use interfaces against instances / objects, not against classes...
Yes I see. This is what I certainly do not want to have = object of same
type implementing different interfaces! That looks like schizophrenia.
this is common practice though, and actually one of the major uses of
interfaces. well, that and allowing different classes to be used in the same
place (AKA: a poor man's duck typing...).
using MI will in effect create the methods, but an interface requires
they already be there;
You consider mutating types. It is irrelevant whether the result
overrides
and existing type or produces a new one. The operation of inheritance
remains exactly same.
It is like to argue that += is not an addition because it replaces the
result.
not really...
it is only a formality IMO that a class be declared as implementing an
interface, but given an interface need not actually change the class that
implements it (and, in fact, the class has to already have the methods in
question before it can implement an interface), it is conceptually
different
IMO from inheritence, which by definition defines the structure of an
object, rather than giving a means of abstracting whatever is already
there...
OK, that is the flawed model of C++ templates: let's take a type A and if
it *occasionally* implements B, we will use it as if it were B! Like if
there were "+" visible in the scope then it should be a number.
This is a non-starter to me, because it is either untyped (then it makes
no
sense to talk about classes, interfaces, types), or else it is structural
types matching, which is incomputable with user-defined types (and is
incompatible with information hiding principle and other software design
practices). Which brings you to the square 1 = untyped.
I don't really see the problem personally...
Here is a picture of tripled doubly-linked web of nodes:
http://www.dmitry-kazakov.de/ada/components.htm#Generic_Doubly_Linked_Web
Each node participates in three lists. In terms of interfaces a node
inherits doubly-linked list interface three times and no merging
happens.
I am not an expert on Ada, but I am not sure I am seeing any
interfaces...
to me, as a guess, it looks more like MI is being used here?...
No, unfortunately Ada cannot this because it also "merges" interfaces as
Java does. The example represents a use case which cannot be handled by
Java-like interfaces. Each element on the figure is in three doubly-linked
lists. If doubly-liked list would be an interface, the element's interface
would have to inherit it three times keeping all three separate. That in
turn would cause a name clash. [My solution is irrelevant here, because it
is not interface/inheritance based.]
To summarize:
interface = abstract type - implementations
abstract type = type - instances
If you have abstract type, you do not need interfaces, they already do all
what you need (provided MI).
The limitation not to have implementations (characterizing interfaces) is
just silly. It does not save you from the conflicts upon composition of
interfaces. There are two competing models of composition:
1. Idempotent: A + A = A
2. Additive: A + A /= A
*Both* models have their use cases. Both models require certain actions to
undertake upon composition of same interfaces independently on whether
implementations are present or not.
then why were you saying that interfaces do not merge?...
in effect, they do merge, and this is why one can't implement the same
interface multiple times, because in effect this neither works, nor does it
make sense conceptually.
MI could probably do this, in the funky way MI tends to work, but tends to
disallow merging the inheritence graph (I had thought this tendency to
fragment was an implementation artifact, but apparently it has some use...).
the more common approach though for multiple-linking like this is, rather
than making the object itself multiply-linkable (although this is common in
C), is to add the object to multiple containers (say, 2 or 3 list objects
owned by different owners...).
even in C, about the only "good" reason to use internal object linking is
that it is convinient, and in many cases there is not much need for an
external container.
[Widespread cited commonplace popcorn about MI is largely rubbish.]
well, yes, in my compilers and such, 128 bit ints and similar are
built
in types...
What about 100 bit? In a higher-level language you write:
type Number is range 1..100;
The compiler is responsible to choose an implementation. The idea of
built-in numeric types is all wrong.
100 bit would not be represented effectively, one can have either 64 or
128 bits, but not 100...
You have no alterative. The point is, the application dictates the
implementation, not reverse. If I need N bits number (properly speaking
a
modular number of modulus 2**N), then I just say so in the language. The
compiler has to find the best possible way to provide me an
implementation
of. The word "best" means: any other solution (including assembler)
would
be less or equally efficient. This is a simple example, but the same
principle must apply to all types without exception.
Predefined types break this principle. They force me to use a type that
is
not exactly one needed by the application. This opens a can of worms.
usually the typesystem provides a similar typeset to those which exist on
the CPU, and to do different would reduce performance.
Nope, that is C stance. The idea of a higher-level language is to abstract
the machine, not to expose it.
?...
then why don't we all go and use Haskell or Prolog?...
I say, the purpose of a higher level language is to get more work done more
effectively, and if this is by hiding or exposing the machine is not
important, only that more work be done, that it be done faster, and that it
be done better...
hmm: "harder, better, faster, stronger...".
When you expose machine types, you cannot describe their semantics in a
machine-independent way, obviously.
doesn't matter when the machines in question implement more-or-less the same
semantics...
That gives you no advantages, whatsoever. If modular 2**32 number fits the
machine register, the compiler would use that far better than me. It is
merely an optimization issue.
maybe, but there is probably some reason that user-variable number types
went away.
COBOL gave us them, and a few languages since, however the common consensus
would seem to be that they don't offer enough advantage to be worth
including them...
the great problem is that, at compile time, niether the programmer nor
the
code may know all of what may happen at runtime, and not all tasks are
possible purely through the use of plain logic code, so the result is
that
one ends up with a good amount of dynamic facilities, such that the
programmer can write code (usually, statically), which causes the app to
begin writing its own code at runtime to accomplish the tasks with which
it
is presented...
Yes, and the language problem is to encircle and insulate this dynamics.
The notion of class (dynamic polymorphism) is such a way.
a class can wrap stuff like this, but so can a plain API.
of course, a class, by itself, will not go about automated code writing, we
need code to do this...
it is also the case that dynamic code writing is a sufficiently expensive
process (and also one not usually included in standard libraries, or FWIW,
even really ANY libraries), that one spends a good deal of code just getting
the prerequisite machinery (assembler, linker, a good number of levels of
code-generators, machinery to compile any of the languages one might want to
use, ...).
so, once all the machinery is in place, then it can be wrapped with nice
APIs, but it doesn't eliminate the need for this machinery (and I am also of
the opinion that, at the present time, there are no really "good" solutions
to all of these problems, although granted there are many fragmentary and
incompatible solutions).
for example, just because we can use Java or C# does not eliminate the need
for the compilers, frameworks, libraries, ... and all this needs code...
to make a simple window and put a button in it, requires heavy involvement
from the OS, hardware, ... and, alas, all this requires lots more code...
so, as the app goes along, it may end up writing a good deal of its
internal
structures at runtime, and having abilities that are generally lacking in
purely statically-compiled apps, such as the ability to "absorb" other
libraries and code into itself, ...
Run-time support is a derivate of the language. It is a question what
belongs there. In my view it must be minimal. The dynamic stuff should be
possible to get at the language level as a set of libraries.
the problem then is when no such libraries exist, then they have to be
written...
if I felt there were a good existing solution to all this, I would not be
making all this myself, and if I still were, I would be cloning their APIs
and similar...
now, for what things there are of use, I will implement them as well.
for example, I had recently started on work to glue my JVM clone to my
existing compiler for JIT purposes, and though not being done exactly in the
way I had originally hoped (I had hoped to JIT directly by a procedural API,
not by production of textual RPNIL code), it is probably good enough...
if anything, the textual format is probably more general, and is more
convinient, although it does not bode as well for the raw speed of the JIT
process (but, hell, it could be slower: I could have been JIT'ing to C code
and running this through my dynamic C compiler...).
well, this is along with me now splitting my GC and typesystem+object system
into separate libraries...
--
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de
.
- Follow-Ups:
- Re: object system...
- From: Dmitry A. Kazakov
- Re: object system...
- References:
- object system...
- From: cr88192
- Re: object system...
- From: Dmitry A. Kazakov
- Re: object system...
- From: cr88192
- Re: object system...
- From: Dmitry A. Kazakov
- Re: object system...
- From: cr88192
- Re: object system...
- From: Dmitry A. Kazakov
- Re: object system...
- From: cr88192
- Re: object system...
- From: Dmitry A. Kazakov
- Re: object system...
- From: cr88192
- Re: object system...
- From: Dmitry A. Kazakov
- Re: object system...
- From: cr88192
- Re: object system...
- From: Dmitry A. Kazakov
- object system...
- Prev by Date: Re: please answer these questions as soon as possible. because i have exam
- Next by Date: Re: Exit criteria
- Previous by thread: Re: object system...
- Next by thread: Re: object system...
- Index(es):