|
From: Laurent Deniau on 3 Apr 2006 12:44 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 3 Apr 2006 14:39 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 4 Apr 2006 03:25 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 4 Apr 2006 04:33 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 4 Apr 2006 15:28
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 |