Re: The Language I want
- From: "Aaron Gray" <ang.usenet@xxxxxxxxx>
- Date: Sun, 8 Mar 2009 19:32:19 -0000
"Dmitry A. Kazakov" <mailbox@xxxxxxxxxxxxxxxxx> wrote in message
news:z9uxovo1m6pj.1urlzkw2mvy1c.dlg@xxxxxxxxxxxxx
On Sun, 8 Mar 2009 15:51:10 -0000, Aaron Gray wrote:
"Dmitry A. Kazakov" <mailbox@xxxxxxxxxxxxxxxxx> wrote in message
news:lr4jk9fmrhg4.1tjxfjqrhonf6.dlg@xxxxxxxxxxxxx
On Sat, 7 Mar 2009 22:09:24 -0000, Aaron Gray wrote:
"Aaron Gray" <ang.usenet@xxxxxxxxx> wrote in message
news:71fi2fFkkubpU1@xxxxxxxxxxxxxxxxxxxxx
I want a OO language with :-- interfaces, ala Java
- multiple inheritance - with fine grain control
No, an abstract type is/has already interface. What is needed is
inheritance of interfaces from concrete types. But no interfaces, it is
a
great evil.
In my model interface cannot contain implemeted methods, abstract classes
can.
Yes, I mean that. Interface as a kid of type makes no any sense.
Yep.
- public, protected, and private, ala C++
No. Visibility is an independent to type issue. It is a property of a
package / module. It has nothing to do with inheritance. So public and
private views only.
no protected members ? Why not ?
Because it is an artefact of C++ design fault which conflates classes and
modules. If you don't then public and private suffice.
I disagree, protected allows you to call or modify methods of your parent
but not to allow using classes to access those protected members. This is
very useful for controlled encapsulation.
If you still disagree could you make your point clearer as I not sure I
understand what you are getting at ?
- C++ style casts to access "hidden" members
No hidden members. There is "private" for that.
Unlike Eiffel and like C++ member maybe overlayed by other members in
inheriting classes. In Eiffle you cannot ever get access to these again,
but
in C++ and my model they maybe accessed via casts, ie X::Y::z
See above. There is no such problem. Derive in a package that has full
view
on the type, end of story.
See above.
No. Constructor / destructor aren't functions. There should be built-in
constructors / destructors with user defined hooks of *properly* typed
subprograms.
They are static functions with special prominence.
No, they are not since you cannot specify their profile staying typed.
Constructor takes "no type" and converts it into "type T," this i
fundamentally inconsistent with the notion of strong typing.
BTW, under static function I understand "compile time function," and not
C++ kludge.
No I still define 'static' as C++'s static in my model.
These "class constructors and distructors" are one off functions called when
a class is "loaded" or "unloaded" ie when it comes into being or dies, this
allows static data members to be dynamically initialized.
BTW. These hooks must be definable for class and for type. AKA the issue
of dispatching from a constructor.
How they are called is platform dependant. I have not started designing
or
defining the platform yet, it will probably be CLR or Java'ish.
It does not depend on any platform. It is again a fundamental issue, you
cannot dispatch so long there is no object, and there is no object while
you are in the constructor. This can be solved only by introducing
constructors of classes.
I think we were talking at cross purposes, see above.
- most things/'units' can exhibit inheritance, for example
modules can inherit other modules so extending them.
First-class modules? That's difficult to make working. I doubt if it can
work.
Dont see any problems with first class modules, can you please list some.
How are you going to check types of the objects declared in dynamically
created module object?
Because everything is static, when a textual module is first loaded it is
compiled into a dll then loaded.
- generics/parameterized polymorphism
No generics. Constrained types instead.
Why ?
Generics is a huge mess.
Real generics, ie not C++'s generics are great they allow very efficient
good code to be generated particularly when combined with inline
functions/methods, saving lots of (physical) typing effort. They are sort of
oposite to polymorphism in a way.
- signatures to allow restricted generacism as well as 'super',
and 'sub', 'parent' and, 'child' restrictors
No, that is weak typing. Ad-hoc supertypes instead.
Signatures are akin to C++0x's concepts although as of yet not as
powerful.
I don't buy weak typing. Typing is either strong or none.
Me too. Have you looked at C++0x's concepts at all ?
- templates or hygenic macros
No templates (which are generics anyway)
Templates or hygenic macros are not generics !
I see no difference. Yes generics as found in Ada are typed, in some meta
sense, while C++ templates are not. Beyond that there is no difference.
Templates or hygenic macros are like the C preprocessors '#define'
statements but with full type safety. Have you looked at Dylan at all ?
http://www.opendylan.org/books/drm/
http://www.opendylan.org/books/drm/Macros
- by devorcing templates from generacism you end up withalot
more
power, there is no way of adding any extra value to C++ templates and
hence
there usefullness is restricted and its back to C preprocessor.
No it can end only in mess.
In C++ templates any value semantics end up in the objects signature
which
means it cannot be used for templating proper.
I am not sure what you mean.
Templates are not C++ templates. With C++ the templates object signature ie
its mangled name in assembler contains all the templates instantiated
parameter types. My generics would too. But my templates do not.
This is another way to say that it is a mess. Note that templates is a
meta
language related to the object one. This is why you can have templates
of
anything. If you need a meta-language, then there is something wrong
with
the object one, obviously. So why not to concentrate on fixing that
first?
Especially when designed form scratch?
I disagree this is a meta language and an object language, it just depend
what modules you include to what the language provides and is applicable
for.
Addition of any feature to the language must be justified. So far nobody
was able to point any reason why a language should have generics /
templates / macros. All arguments are based on an inability the given
types
system to express a certain class of types. See Stepanov's argument about
generic max, for example. These arguments are bogus. Fix the type system
and everything will be OK.
mmm, I disagree, both generics and templates save an awful ammount of
typing.
- multimethods, both global and on classes
Multiple dispatch.
Yes, but in a contained fashon using the 'virtual' keyword :)
There should be nothing but virtual. If you don't want a procedure to
dispatch in some parameter, you would declare it on the class rather than
on the type. It will still dispatch but on the class of the class.
This is an argument I both agree with and disagree, this is an old one. For
simplicity sake and expected behaviour sake I agree. I believe D takes this
approach.
Also the compiler should be able to decide how to implement things, virtual
or non virtual, or inlined, given the context such as generic parameters if
there are any, and small world syndrome / whole program optimization should
allow the right decisions to be made.
I would like a nonvirtual keyword then :)
Still not made up my mind on this one completely though.
You probably mean the interface of a compilation unit and its separation
from the implementation. Everything visible in the declarative part of a
unit is, well, visible.
Unless it is marked private, protected.
When private then invisible. Protected has no meaning.
Yes it does it protects members from access by users, but allows access from
sub classes.
Protected types, that is ones which can accessed concurrently. Protected
type is an OO view on concurrency, while tasks are a functional one.
What ?
Protected object is passive. Its operations are said to be protected.
There
are three kinds of:
- immutable, change no state, synchronous can be executed simultaneously
when you have multi-core;
- mutable, change state, synchronous, mutually exclusive;
- entries, change state, asynchronous, mutually exclusive, can be awaited
for (have a queue).
Protected objects are sufficiently more effective than other means of task
communication, like rendezvous, for example.
??? you've lost me here.
+ contracted exceptions
try, throw, catch, and finally.
I meant that each operation has a contract of the exceptions, which may
propagate out of it. The exception contracts are statically checked and
inherited from parent typed. (Java, but with lessons learned.)
Okay. Please elaborate.
+ statically checked pre-/postconditions, invariants
Yes like Eiffle, nice, I had though about these.
No, unlike Eiffel. Meyer did it wrong, IMO. In Eiffel they are assertions.
I meant correctness checks, i.e. everything happens before the run.
Otherwise it makes no sense.
Really you want both, compile time assertions and runtime ones if they are
not resolvable at compile time. Maybe they want to be separate syntatically
though.
+ abstract interfaces for standard container types (array, record)
+ abstract interfaces for referential types
+ abstract interfaces for aggregates
+ dynamically constrained types
Runtime typing, runtime constraints ? Please clarify ?
Consider an array type, like string. String is unconstrained because its
length is unknown. But this does not mean you need dynamically allocated
strings like in C++. In 90% cases all string objects are constrained (have
known length) on the caller side. But the callee is works with an
unconstrained formal object. This is a very powerful model of type
parametrization without generics.
Pretty useless in this example, can you give another that demonstrates rall
value ?
+ downward closures
please elaborate.
Passing a function as a parameter. The function carries its context with.
Please give an example.
+ fully OO 1: no free functions, any function is a method of the types
of
every its argument and the type of the result(s). I think this would be
difficult to reconcile with fashionable first-class functions
No we have free functions they are fine as long as they are scopesd
within a
namespace, module, or package.
To me any function is virtual. I see no reason to have other kind of
functions. They breaks out of the model. If you have multiple dispatch,
free functions vanish.
Not necessarily ? Please elaborate.
+ fully OO 3: every class has a type (polymorphic objects)
A class is an implementation of a type, not necessarily polymorphic
thoght,
it may just be aload of inlines !
Class is a set of types. The set of values of the type of the class is a
closure of the sets of values of the types from the class.
Our terminology is very different.
+ separation of classes and types (polymorphic vs. specific objects)
types are implemented by other types or classes. We seem to have
different
models for types and classes, I donot agree with your distinction.
Yes
+ an ability to have polymorphic objects with value semantics (follows
from OO 2)
Dont follow please explain your model properly.
See above.
Still dont understand.
Any contenders ?
We will forget about the contenders :)
The problem is that to make that list right is a huge problem. You
forgot
the mist important thing, the requirements of how the above aspects
shall
be implemented, Say you add to multiple dispatch and obvious
requirement:
"no dispatch may fail at run time," and you get a serious problem, since
nobody, AFAIK, knows how to achieve that.
I was not aware of anything like this with multiple dispatch could
produce
exceptions if there are undefined usages though.
Lisp's MOF seems to have implemented MD fine.
Could you please elaborate and maybe give an example please.
When you derive S from T and inherit some f, the language shall force you
to define all implementations of f for all possible combinations of the
parameters if it cannot invent an implementation by itself. Consider:
f : T x P
you derive S from T, now there are
f : T x P
-----------------------------
f : S x P (inherited)
let's derive R from P, now we have
f : T x P
f : S x P
-----------------------------
f : T x R (inherited)
f : S x R (inherited)
At any step, the compiler shall ensure that each slot in the dispatching
table of f is defined either per inheritance or else by the programmer. No
undefined slots.
Okay.
You add a trivial requirement
that your first-class types would be all equal in the sense that you can
inherit from any. Any means any e.g. integer, task, module (you wanted
it), type (here as a type of type!) and you will see where the devil
lives...
ineriting from an integer gives the ability for a class/type to look like
an
integer but to over ride an integers behaviour, setter and getters will
be
implemented like this.
As a type of a type you mean type variables ?
Yep
I have been studying this devil for years, and think I have mainly
rational
"working" solutions.
The problem is that people understand commonly words differently. So when
you list features of a language the mental picture may vary in a range
that
can include both opposites. So to me, it is more important to lay down the
language design principles, general goals. For example,
- static checkability
- separate compilation / large systems design support
- portability
- consistency
- regularity
- readability
- abstraction level (values <of types <of classes <of ?)
- efficiency
- minimal set of built-in / "magical" things
etc
Thanks for the examination Dmitry, that was good.
You are welcome.
Still matters to resolve :)
Cheers,
Aaron
.
- Follow-Ups:
- Re: The Language I want
- From: Dmitry A. Kazakov
- Re: The Language I want
- From: Aaron Gray
- Re: The Language I want
- References:
- The Language I want
- From: Aaron Gray
- Re: The Language I want
- From: Aaron Gray
- Re: The Language I want
- From: Dmitry A. Kazakov
- Re: The Language I want
- From: Aaron Gray
- Re: The Language I want
- From: Dmitry A. Kazakov
- The Language I want
- Prev by Date: Re: The Language I want
- Next by Date: Re: The Language I want
- Previous by thread: Re: The Language I want
- Next by thread: Re: The Language I want
- Index(es):
Relevant Pages
|