From: Laurent Deniau on
Dmitry A. Kazakov wrote:
> On Mon, 03 Apr 2006 15:10:57 +0200, Laurent Deniau wrote:
>>Dmitry A. Kazakov wrote:
>>>Of course it is. The value of a polymorphic type is itself polymorphic.
>>Could you give me an example of polymorphic value?
> class A {...};
> class B : public A {...};
>
> A * X = new B ();
>
> X points to a polymorphic object (of which value is also polymorphic.) It

You claimed that the *value* is polymorphic. Please show me the
polymorphic value instead of a pointer to it. This example shows exactly
what I said, no polymorphism without pointer.

> So the type of a polymorphic object is always known, otherwise (remember,
> it is a behavioral notion of ADT) you wouldn't be able to do anything with
> it. No type - no methods, no methods - no access.

Java interfaces don't need to know anything *static* about an object to
invoke one of its method. Haskell even allows to provide default
implementation. BTW, this method can be an accessor.

>>>Take a hierarchy of numerals. Start from ordinals, proceed to fields, then
>>>go to matrices. Add slices and submatrices. Add physical dimensions to each
>>>leaf of the hierarchy. Along the way ensure optimal memory and performance.
>>>Add the axis of intervals (interval arithmetic.) Continue to the fuzzy case
>>>based on intervals. [ I know no language capable to do this. ]
>>
>>C++ is able to do that with no needs for a hierachy. What you are
>>descibing here requires parametric polymorphism (C++ template) and some
>>metaprogramming. Not my concern here.
>
>
> But mine. Dynamic (true) polymorphism is to replace parametric (fake) one.

So why do you claim that no language can't do what you described above.
Call it fake, it fulfilled your request. The cons is that the code is
strongly instrusive into the type system (concepts may relax this point)
and making the code harder to extend.

>>>The key requirement for MD is in my view: dispatch
>>>shall never fail in a legal program.
>>
>>What about very large scale programs (extremly complex) written in
>>dynamically typed languages (see article "Haskell vs. Erlang,
>>Reloaded")? Static typing is one tool amongst others to help the
>>programmer to detect errors at compile time and to help the compiler to
>>make optimizations. But it also often requires to write larger and more
>>complex code (to statisfy the type system constraints). It is far from
>>being the answer to all problems.
>
>
> Sorry, but I don't see how a run-time failure to dispatch might help here.

To inform you that either you have a bug in your program or you forgot
to provide something. AFAIK, runtime type failures occur in all
languages (except in all-program analysis), therefore you must test your
code.

a+, ld.

From: Dmitry A. Kazakov on
On Mon, 03 Apr 2006 18:44:52 +0200, Laurent Deniau wrote:

> Dmitry A. Kazakov wrote:
>> On Mon, 03 Apr 2006 15:10:57 +0200, Laurent Deniau wrote:
>>>Dmitry A. Kazakov wrote:
>>>>Of course it is. The value of a polymorphic type is itself polymorphic.
>>>Could you give me an example of polymorphic value?
>> class A {...};
>> class B : public A {...};
>>
>> A * X = new B ();
>>
>> X points to a polymorphic object (of which value is also polymorphic.) It
>
> You claimed that the *value* is polymorphic. Please show me the
> polymorphic value instead of a pointer to it. This example shows exactly
> what I said, no polymorphism without pointer.

It is no matter. The dereferenced pointer gives that value. But, OK, in Ada
you can have it without any pointers:

declare
Y : B;
X : A'Class := B;

C++ could have it to if it had different names for A and A'Class.

>> So the type of a polymorphic object is always known, otherwise (remember,
>> it is a behavioral notion of ADT) you wouldn't be able to do anything with
>> it. No type - no methods, no methods - no access.
>
> Java interfaces don't need to know anything *static* about an object to
> invoke one of its method.

If you don't know anything, how can you know its methods? I'm saying almost
trivial thing. To call a method, send a message etc, you have to know that
the thing has the method, accepts any messages etc. This constitutes a
class of things. The closure of that class is a type. The values of that
type are polymorphic. In a language where any message can be sent to any
object, you would soon forget about that type. But it is still present.

>>>>Take a hierarchy of numerals. Start from ordinals, proceed to fields, then
>>>>go to matrices. Add slices and submatrices. Add physical dimensions to each
>>>>leaf of the hierarchy. Along the way ensure optimal memory and performance.
>>>>Add the axis of intervals (interval arithmetic.) Continue to the fuzzy case
>>>>based on intervals. [ I know no language capable to do this. ]
>>>
>>>C++ is able to do that with no needs for a hierachy. What you are
>>>descibing here requires parametric polymorphism (C++ template) and some
>>>metaprogramming. Not my concern here.
>>
>> But mine. Dynamic (true) polymorphism is to replace parametric (fake) one.
>
> So why do you claim that no language can't do what you described above.
> Call it fake, it fulfilled your request.

No it does not.

Example 1: write a calculator dealing with things above.

Example 2: provide all usual cross operations: matrix by scalar, submatrix
by matrix, all sorts of dimensioned matrices by differently dimensioned
matrices etc.

Note that the problem of geometrical explosion of variants is still
present. Switching from one sort of polymorphism to another really changes
nothing. In terms of dispatching tables, static polymorphism defines only
the diagonal elements. It is no runner, alone for that reason.

>>>>The key requirement for MD is in my view: dispatch
>>>>shall never fail in a legal program.
>>>
>>>What about very large scale programs (extremly complex) written in
>>>dynamically typed languages (see article "Haskell vs. Erlang,
>>>Reloaded")? Static typing is one tool amongst others to help the
>>>programmer to detect errors at compile time and to help the compiler to
>>>make optimizations. But it also often requires to write larger and more
>>>complex code (to statisfy the type system constraints). It is far from
>>>being the answer to all problems.
>>
>> Sorry, but I don't see how a run-time failure to dispatch might help here.
>
> To inform you that either you have a bug in your program or you forgot
> to provide something.

That is exactly the problem. It is very easy to forget something among that
number of variants. My point is that because all of these variants are
statically known, this an obvious candidate for static checks, to ensure
that each variant is defined this or that way and is *consistent* with the
definitions of other variants. To force the programmer to do this
explicitly would be inhumane, so I'm looking for more powerful techniques.
Delegation does not look good, however, it is an important technique for
other things. Maybe it could be a metatype to determine how one variants
define others. Maybe, it could be made on the class basis. I'm making no
proposal, just thinking aloud... (:-))

> AFAIK, runtime type failures occur in all
> languages (except in all-program analysis), therefore you must test your
> code.

It is just too late and hopeless because of the number of variants.

Dynamic languages are very flexible, easier to implement and research. For
this reason I expect that sooner or later, from there would come a
technique to cope with the problem. If proved consistent it could be then
adopted for more conservative statically typed languages.

--
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de
From: Dmitry A. Kazakov on
On Mon, 3 Apr 2006 20:39:22 +0200, Dmitry A. Kazakov wrote:

> It is no matter. The dereferenced pointer gives that value. But, OK, in Ada
> you can have it without any pointers:
>
> declare
> Y : B;
> X : A'Class := B;

X : A'Class := Y;

of course.

--
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de
From: Laurent Deniau on
Dmitry A. Kazakov wrote:
> On Mon, 03 Apr 2006 18:44:52 +0200, Laurent Deniau wrote:
>>Dmitry A. Kazakov wrote:
> It is no matter. The dereferenced pointer gives that value. But, OK, in Ada
> you can have it without any pointers:
>
> declare
> Y : B;
> X : A'Class := Y;

It does not prove anything (and I don't know Ada object internal
representation), how do you know that X and Y are not a pointers? In
Java does not have pointers because all objects are pointers (no need
for a special notation and nobody cares). C# is more intrusive on
internal layouts and it allows different notation. Haskell does not have
pointers too, but all data type (user defined types) are disguised
pointers (AFAIU).

> C++ could have it to if it had different names for A and A'Class.

In C++, polymorphism is always achieved through pointers (e.g. this).

>>>So the type of a polymorphic object is always known, otherwise (remember,
>>>it is a behavioral notion of ADT) you wouldn't be able to do anything with
>>>it. No type - no methods, no methods - no access.
>>
>>Java interfaces don't need to know anything *static* about an object to
>>invoke one of its method.
>
>
> If you don't know anything, how can you know its methods?

No magic here. Half of the existing main stream languages don't need to
know the type of an object to find applicable methods.

> I'm saying almost
> trivial thing. To call a method, send a message etc, you have to know that
> the thing has the method, accepts any messages etc.

Not on the caller side.

> This constitutes a
> class of things. The closure of that class is a type. The values of that
> type are polymorphic.

Values are not polymorphic, by definition.

> In a language where any message can be sent to any
> object, you would soon forget about that type. But it is still present.

what is the type of obj in:

id obj = [String newWith "a"]; // objective-C
my obj = new_string("a"); // perl
(setf obj (make-string 1 :initial-element "a")) // Lisp
var obj = 'a'; // Javascript
$obj = 'a'; // PHP
obj = 'a' // Python

nobody knows and what is nice is that nobody cares, but it still
represents one of the most useful object of languages.

>>>>>Take a hierarchy of numerals. Start from ordinals, proceed to fields, then
>>>>>go to matrices. Add slices and submatrices. Add physical dimensions to each
>>>>>leaf of the hierarchy. Along the way ensure optimal memory and performance.
>>>>>Add the axis of intervals (interval arithmetic.) Continue to the fuzzy case
>>>>>based on intervals. [ I know no language capable to do this. ]
>>>>
>>>>C++ is able to do that with no needs for a hierachy. What you are
>>>>descibing here requires parametric polymorphism (C++ template) and some
>>>>metaprogramming. Not my concern here.
>>>
>>>But mine. Dynamic (true) polymorphism is to replace parametric (fake) one.
>>
>>So why do you claim that no language can't do what you described above.
>>Call it fake, it fulfilled your request.
>
>
> No it does not.
>
> Example 1: write a calculator dealing with things above.

Not a problem.

> Example 2: provide all usual cross operations: matrix by scalar, submatrix
> by matrix, all sorts of dimensioned matrices by differently dimensioned
> matrices etc.

Already done. Search for SL++, a library I wrote in 1998. It provides
all what you says. It also handle dozen of matrix structures (Vector,
Diagonal, [Row|Col]Major, [Upper|Lower]Triangular, Sparse, etc...),
iterators, submatrix, implicit loops... I think that today much better
libraries exists since C++ is better supported. With actual compilers
and existing libraries, SL++ could be rewritten in a much simpler and
shorter way (using SL valarray for example).

> Note that the problem of geometrical explosion of variants is still
> present.

But in this case, it is managed by the compiler.

> Switching from one sort of polymorphism to another really changes
> nothing.

Oh yes it does!

> In terms of dispatching tables, static polymorphism defines only
> the diagonal elements. It is no runner, alone for that reason.

I don't know what you call "static polymorphism", but static binding
doen't need table. But if you have subtyping, coercion and overloading
(ad-hoc polymorphism), then the compiler may have some work to select
the right method. It may be even more complex if you have parametric
polymorphism and namespaces on top of these.

>>>>>The key requirement for MD is in my view: dispatch
>>>>>shall never fail in a legal program.
>>>>
>>>>What about very large scale programs (extremly complex) written in
>>>>dynamically typed languages (see article "Haskell vs. Erlang,
>>>>Reloaded")? Static typing is one tool amongst others to help the
>>>>programmer to detect errors at compile time and to help the compiler to
>>>>make optimizations. But it also often requires to write larger and more
>>>>complex code (to statisfy the type system constraints). It is far from
>>>>being the answer to all problems.
>>>
>>>Sorry, but I don't see how a run-time failure to dispatch might help here.
>>
>>To inform you that either you have a bug in your program or you forgot
>>to provide something.
>
>
> That is exactly the problem. It is very easy to forget something among that
> number of variants. My point is that because all of these variants are
> statically known, this an obvious candidate for static checks, to ensure
> that each variant is defined this or that way and is *consistent* with the
> definitions of other variants.

But there is no way for a compiler which allows to use ADT and to make
libraries (separate compilation), to detect such inconsistency at
compile-time. Even Haskell, one of the most advanced strongly statically
typed language does some runtime check (and raise errors) in such case.

> To force the programmer to do this
> explicitly would be inhumane, so I'm looking for more powerful techniques.
> Delegation does not look good,

Delegation of behavior is slow, but powerful.
Delegation of type is fast, less powerful, and it may be an answer to
most common problems.

> Dynamic languages are very flexible, easier to implement and research. For
> this reason I expect that sooner or later, from there would come a
> technique to cope with the problem. If proved consistent it could be then
> adopted for more conservative statically typed languages.

We have been waiting for about 25 years now, in the mean time I still
have to write projects ;-)

a+, ld.

From: Dmitry A. Kazakov on
On Tue, 04 Apr 2006 10:33:13 +0200, Laurent Deniau wrote:

> Dmitry A. Kazakov wrote:
>> On Mon, 03 Apr 2006 18:44:52 +0200, Laurent Deniau wrote:
>>>Dmitry A. Kazakov wrote:
>> It is no matter. The dereferenced pointer gives that value. But, OK, in Ada
>> you can have it without any pointers:
>>
>> declare
>> Y : B;
>> X : A'Class := Y;
>
> It does not prove anything (and I don't know Ada object internal
> representation), how do you know that X and Y are not a pointers?

Because they are not, provided, that "pointer" denotes a corresponding
language term. If you mean something else, then you should give a
definition, which would be quite non-trivial. Anyway, X is allocated on the
stack, theoretically it can be allocated in a register.

> In
> Java does not have pointers because all objects are pointers (no need
> for a special notation and nobody cares). C# is more intrusive on
> internal layouts and it allows different notation. Haskell does not have
> pointers too, but all data type (user defined types) are disguised
> pointers (AFAIU).

See above. This sentence has no meaning in language terms. You should not
mix semantics and implementation. Semantically I can copy polymorphic
objects, that means that their values aren't bound to definite memory
locations. As for implementation can be any if it conforms to the
semantics.

>>>>So the type of a polymorphic object is always known, otherwise (remember,
>>>>it is a behavioral notion of ADT) you wouldn't be able to do anything with
>>>>it. No type - no methods, no methods - no access.
>>>
>>>Java interfaces don't need to know anything *static* about an object to
>>>invoke one of its method.
>>
>> If you don't know anything, how can you know its methods?
>
> No magic here. Half of the existing main stream languages don't need to
> know the type of an object to find applicable methods.

This is in an obvious contradiction: "anything" includes "to find
applicable methods."

>> I'm saying almost
>> trivial thing. To call a method, send a message etc, you have to know that
>> the thing has the method, accepts any messages etc.

>> This constitutes a
>> class of things. The closure of that class is a type. The values of that
>> type are polymorphic.
>
> Values are not polymorphic, by definition.

OK, you can define values as non-polymorphic, but that would exclude
polymorphism. I assume that there is nothing but values and types of. If
the thing, on which dispatch happens, is not value, then either it does not
exist or it is something beyond the types system. I don't see any good way
how you could get out of this. And there is no reason why polymorphic
things should be no values.

>> In a language where any message can be sent to any
>> object, you would soon forget about that type. But it is still present.
>
> what is the type of obj in:
>
> id obj = [String newWith "a"]; // objective-C
> my obj = new_string("a"); // perl
> (setf obj (make-string 1 :initial-element "a")) // Lisp
> var obj = 'a'; // Javascript
> $obj = 'a'; // PHP
> obj = 'a' // Python

Its type is the class of copyable objects (ones having '='). It is not even
"the class of all objects", because highly likely it would be impossible to
have because of self recursion.

>>>>>C++ is able to do that with no needs for a hierachy. What you are
>>>>>descibing here requires parametric polymorphism (C++ template) and some
>>>>>metaprogramming. Not my concern here.
>>>>
>>>>But mine. Dynamic (true) polymorphism is to replace parametric (fake) one.
>>>
>>>So why do you claim that no language can't do what you described above.
>>>Call it fake, it fulfilled your request.
>>
>> No it does not.
>>
>> Example 1: write a calculator dealing with things above.
>
> Not a problem.

Hmm, with C++ templates? Show me the code.

>> Example 2: provide all usual cross operations: matrix by scalar, submatrix
>> by matrix, all sorts of dimensioned matrices by differently dimensioned
>> matrices etc.
>
> Already done. Search for SL++, a library I wrote in 1998. It provides
> all what you says. It also handle dozen of matrix structures (Vector,
> Diagonal, [Row|Col]Major, [Upper|Lower]Triangular, Sparse, etc...),
> iterators, submatrix, implicit loops...

Can all these types be mixed? Can I multiply a diagonal matrix to a
triangular one and get a triangular result? All that without MD?

Anyway, why don't you use this as an example, rather than those ill sharks?
(:-))

>> Note that the problem of geometrical explosion of variants is still
>> present.
>
> But in this case, it is managed by the compiler.

>> Switching from one sort of polymorphism to another really changes
>> nothing.
>
> Oh yes it does!

But without considering any concrete case, we could say that if there were
a parametric solution of the problem, then it should be transformable into
a dynamically polymorphic one. I mean the following. I can mentally move
parameters from types (generic/template types) to the tags (of concrete
types.) So anything the compiler does for parametric types and their
methods it can also do for normal types. In short, Add(T<P1> x, T<P2> y) is
nothing better than Add(T1 x, T2 y) in terms of the total number of
variants.

>> In terms of dispatching tables, static polymorphism defines only
>> the diagonal elements. It is no runner, alone for that reason.
>
> I don't know what you call "static polymorphism", but static binding
> doen't need table. But if you have subtyping, coercion and overloading
> (ad-hoc polymorphism), then the compiler may have some work to select
> the right method. It may be even more complex if you have parametric
> polymorphism and namespaces on top of these.

Yes. But how this reduces the number of variants?

>> That is exactly the problem. It is very easy to forget something among that
>> number of variants. My point is that because all of these variants are
>> statically known, this an obvious candidate for static checks, to ensure
>> that each variant is defined this or that way and is *consistent* with the
>> definitions of other variants.
>
> But there is no way for a compiler which allows to use ADT and to make
> libraries (separate compilation), to detect such inconsistency at
> compile-time.

Some inconsistencies, not all of them. And the compiler should have some
additional information about the structure of the methods. What I miss in
all proposals is that additional information, like commutativity. Note that
frozen methods, and enforced prologues and epilogues (as in found in
constructors and destructors) is also that sort of information.

--
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de