From: Adam Beneschan on
On Nov 16, 2:28 pm, "Dmitry A. Kazakov" <mail...(a)dmitry-kazakov.de>
wrote:

>
> No, what I have in mind is that each time a new type is derived, we could
> somehow ensure that the whole row M+1 (from N x M+1) is filled either by a
> overriding or per a reasonable inheritance. The major problem is that we
> cannot see all Ns when we do M+1.
>
> The idea of deriving both types in one package looks like an attempt to
> control the places where we can expand the table N x M. That is not enough
> to enforce completeness of the table in the above sense.
>
> There should be something more strong, but also more liberal in terms of
> modularization. Obviously to derive from all types related via a shared
> primitive operation in one package is awful (and sometimes just impossible
> within the given parent-child hierarchy of packages).

.....

> Yep, this is what I meant. The compiler should require to override *all*
> combinations:
>
>    type T2 is new T1 with ...;
>    overriding
>       procedure Some_Operation (X : T2; Y : T2);
>         -- Error!
>
>    overriding
>       procedure Some_Operation (X : T2; Y : T2);
>    overriding
>       procedure Some_Operation (X : T1; Y : T2);
>    overriding
>       procedure Some_Operation (X : T2; Y : T1);
>          -- OK
>
> Yes, this is tedious, but the programmer should know what we does when he
> declares a multi-method. This is the semantics of - there are n**2
> combinations which do potentially different things. If there are only n
> combinations, that is another case, which should *not* look MD, because it
> is not. I think it should somehow use tuples instead. The error should
> happen upon tuple construction, not in the call. For the reader it should
> be clear that there is only one tag. I have no idea how to spell that
> syntactically or by other means.

It appears to me that we're talking at cross-purposes.
I was trying to solve one particular class of problems;
you seem to be trying to solve the entire Multiple
Dispatch problem. I believe that when I first thought
about making this proposal, I was assuming that a fully
general multiple dispatch wasn't ever going to be part
of the language, so I was thinking about an improvement
for one particular case I had run into.

Here's an example of the sort of problem I'm thinking
about: Suppose you want to define an abstract type that
represents a document, which could be a plain ASCII
text file, a Word document, a PDF file, etc., that all
have in common that they consist of sequences of
"characters" and "other elements of some sort". Some
of the documents may also have formatting information
or other good stuff, but these won't be common to all
documents.

You want to write a package that deals with documents
and particularly with the text (characters) in the
documents. The type of document (plain text, Word,
etc.) won't be known until run time. Some of the
operations you want to provide are: search for given
text in the document, and return "markers" that point
to the beginning and end of the text that is found; and
move text from one point to another in the document.

A natural way to do this, it seems, would be to define
a Document as an abstract type, and let other packages
(Plaintext_Documents, Word_Documents, PDF_Documents,
etc.) define concrete types as extensions of that type
for plain text, Word documents, PDF documents, and so
on. You also want to define, say, a Text_Region type
that represents a region of text in a document, and a
Marker type that represents a particular point in the
document text, between two characters. The Text_Region
and Marker types should be abstract also, since we
don't know how they'd be implemented for different
document types; for a plain text document, a Marker is
probably just a string index, in essence, but the
Word_Documents and PDF_Documents might unpack a file
into some complex internal data structure when it reads
it, so a Marker for those document types might contain
pointers into the internal data structure, or
something.

So it seems natural to write the package like this
(along with other operations):

package Documents is

type Document is abstract tagged private;
type Text_Region is abstract tagged private;
type Marker is abstract tagged private;

function Search_For_Text (Doc : Document; Text : String)
return Text_Region is abstract;
-- I'm assuming here that it would return some sort of
-- "no region" value if the text is not found
function Beginning_Of (Reg : Text_Region) return Marker
is abstract;
function End_Of (Reg : Text_Region) return Marker
is abstract;

procedure Move_Text (Doc : in out Document;
From : in Text_Region;
To : in Marker)
is abstract;

end Documents;

The last would cut the text represented by the From
region and move it to the point specified by "To". (It
would be up to the packages to figure out how to move
formatting information or other information in an
appropriate way.)

Of course, Move_Text can't be declared because it is a
primitive operation of more than one tagged type.
Actually, none of the functions can be declared,
either, but I want to focus on the Move_Text procedure.
You might want to call Move_Text with a
Word_Documents.Document, Word_Documents.Text_Region,
and Word_Documents.Marker, or similarly with three
objects all with types from the PDF_Documents or
Plaintext_Documents package, but you would never want
to mix objects from two different packages. And that
was the purpose of the proposal I was thinking of
making: to allow for restricted use of multiple
dispatch for cases like this (and this is a situation I
believe I've run into more than once), in which
Move_Text could be declared but could only be called if
the parameters' specific types all come from the same
package, checked at runtime if necessary. The
Move_Text procedure would be inherited in each of the
other packages (Plaintext_Documents, etc.), with types
from that package, but there would not be any inherited
Move_Text that would involve types from different
packages. (This was an idea I first thought about a
long time ago, but eventually abandoned; I really
hadn't thought about how to deal with the functions.)

There are workarounds, of course. As I responded to
the original poster in this thread, you can make some
of the parameters to Move_Text class-wide, and the
concrete procedures would check to make sure the actual
tags for the class-wide parameters are correct---or
just doing a type conversion will do the check:

package body Word_Documents is

overriding
procedure Move_Text (Doc : in out Document;
From : in Documents.Text_Region'Class;
To : in Documents.Marker'Class) is
X_From : Text_Region renames Text_Region(From);
X_To : Marker renames Marker(To);
...

I think that's correct. Anyway, those will raise
Constraint_Error if the parameters are from the wrong
package.

However, I consider that to be a workaround (maybe
others don't think it's that bad), which is why I was
thinking about making this proposal---to make things
work more "naturally", without a workaround, in this
sort of situation that I've run into multiple times.
I'm not sure what your idea is trying to solve (other
than "making multiple dispatch perfect"); but even if
it does make general multiple dispatch available, your
way of doing things would not solve anything in this
sort of case, because you would require Move_Text to be
overridden for every possible combination of children
of the types, which makes it unusable and means that
even with your Grand Solution To Everything, those of
us who want to implement something like the above would
have to go back to using the workaround.

That's why I think we're not on the same page---we're
trying to solve two different and unrelated problems
that seem only superficially related. Maybe we can't
solve them both.

-- Adam


From: Dmitry A. Kazakov on
On Tue, 17 Nov 2009 14:10:54 -0800 (PST), Adam Beneschan wrote:

> On Nov 16, 2:28�pm, "Dmitry A. Kazakov" <mail...(a)dmitry-kazakov.de>
> wrote:
>
>> No, what I have in mind is that each time a new type is derived, we could
>> somehow ensure that the whole row M+1 (from N x M+1) is filled either by a
>> overriding or per a reasonable inheritance. The major problem is that we
>> cannot see all Ns when we do M+1.
>>
>> The idea of deriving both types in one package looks like an attempt to
>> control the places where we can expand the table N x M. That is not enough
>> to enforce completeness of the table in the above sense.
>>
>> There should be something more strong, but also more liberal in terms of
>> modularization. Obviously to derive from all types related via a shared
>> primitive operation in one package is awful (and sometimes just impossible
>> within the given parent-child hierarchy of packages).
>
> ....
>
>> Yep, this is what I meant. The compiler should require to override *all*
>> combinations:
>>
>> � �type T2 is new T1 with ...;
>> � �overriding
>> � � � procedure Some_Operation (X : T2; Y : T2);
>> � � � � -- Error!
>>
>> � �overriding
>> � � � procedure Some_Operation (X : T2; Y : T2);
>> � �overriding
>> � � � procedure Some_Operation (X : T1; Y : T2);
>> � �overriding
>> � � � procedure Some_Operation (X : T2; Y : T1);
>> � � � � �-- OK
>>
>> Yes, this is tedious, but the programmer should know what we does when he
>> declares a multi-method. This is the semantics of - there are n**2
>> combinations which do potentially different things. If there are only n
>> combinations, that is another case, which should *not* look MD, because it
>> is not. I think it should somehow use tuples instead. The error should
>> happen upon tuple construction, not in the call. For the reader it should
>> be clear that there is only one tag. I have no idea how to spell that
>> syntactically or by other means.
>
> It appears to me that we're talking at cross-purposes.

No, it is the same problem of MD. It has some special cases like
multi-methods, which are simpler, but it is still MD. The example you
provided is full MD. You have three hierarchies:

Document'Class, Text_Region'Class, Marker'Class

An operation can be primitive in any combinations of types from these
hierarchies.

> I was trying to solve one particular class of problems;
> you seem to be trying to solve the entire Multiple
> Dispatch problem. I believe that when I first thought
> about making this proposal, I was assuming that a fully
> general multiple dispatch wasn't ever going to be part
> of the language, so I was thinking about an improvement
> for one particular case I had run into.
>
> Here's an example of the sort of problem I'm thinking
> about: Suppose you want to define an abstract type that
> represents a document, which could be a plain ASCII
> text file, a Word document, a PDF file, etc., that all
> have in common that they consist of sequences of
> "characters" and "other elements of some sort". Some
> of the documents may also have formatting information
> or other good stuff, but these won't be common to all
> documents.
>
> You want to write a package that deals with documents
> and particularly with the text (characters) in the
> documents. The type of document (plain text, Word,
> etc.) won't be known until run time. Some of the
> operations you want to provide are: search for given
> text in the document, and return "markers" that point
> to the beginning and end of the text that is found; and
> move text from one point to another in the document.
>
> A natural way to do this, it seems, would be to define
> a Document as an abstract type, and let other packages
> (Plaintext_Documents, Word_Documents, PDF_Documents,
> etc.) define concrete types as extensions of that type
> for plain text, Word documents, PDF documents, and so
> on. You also want to define, say, a Text_Region type
> that represents a region of text in a document, and a
> Marker type that represents a particular point in the
> document text, between two characters. The Text_Region
> and Marker types should be abstract also, since we
> don't know how they'd be implemented for different
> document types; for a plain text document, a Marker is
> probably just a string index, in essence, but the
> Word_Documents and PDF_Documents might unpack a file
> into some complex internal data structure when it reads
> it, so a Marker for those document types might contain
> pointers into the internal data structure, or
> something.
>
> So it seems natural to write the package like this
> (along with other operations):
>
> package Documents is
>
> type Document is abstract tagged private;
> type Text_Region is abstract tagged private;
> type Marker is abstract tagged private;
>
> function Search_For_Text (Doc : Document; Text : String)
> return Text_Region is abstract;
> -- I'm assuming here that it would return some sort of
> -- "no region" value if the text is not found
> function Beginning_Of (Reg : Text_Region) return Marker
> is abstract;
> function End_Of (Reg : Text_Region) return Marker
> is abstract;
>
> procedure Move_Text (Doc : in out Document;
> From : in Text_Region;
> To : in Marker)
> is abstract;
>
> end Documents;
>
> The last would cut the text represented by the From
> region and move it to the point specified by "To". (It
> would be up to the packages to figure out how to move
> formatting information or other information in an
> appropriate way.)
>
> Of course, Move_Text can't be declared because it is a
> primitive operation of more than one tagged type.
> Actually, none of the functions can be declared,
> either, but I want to focus on the Move_Text procedure.
> You might want to call Move_Text with a
> Word_Documents.Document, Word_Documents.Text_Region,
> and Word_Documents.Marker, or similarly with three
> objects all with types from the PDF_Documents or
> Plaintext_Documents package, but you would never want
> to mix objects from two different packages.

As an example consider these operations:

procedure Cut
( Doc : in out Document;
From : in Text_Region;
Clipboard : in out Document
);
procedure Paste
( Clipboard : in Document;
Doc : in out Document;
To : in Marker
);

> And that
> was the purpose of the proposal I was thinking of
> making: to allow for restricted use of multiple
> dispatch for cases like this (and this is a situation I
> believe I've run into more than once), in which
> Move_Text could be declared but could only be called if
> the parameters' specific types all come from the same
> package, checked at runtime if necessary. The
> Move_Text procedure would be inherited in each of the
> other packages (Plaintext_Documents, etc.), with types
> from that package, but there would not be any inherited
> Move_Text that would involve types from different
> packages. (This was an idea I first thought about a
> long time ago, but eventually abandoned; I really
> hadn't thought about how to deal with the functions.)

So if you derived ASCII_Text from Plain_Text you would lose Move_Text if
you forgot to derive from Text_Region and Marker?

> There are workarounds, of course. As I responded to
> the original poster in this thread, you can make some
> of the parameters to Move_Text class-wide, and the
> concrete procedures would check to make sure the actual
> tags for the class-wide parameters are correct---or
> just doing a type conversion will do the check:
>
> package body Word_Documents is
>
> overriding
> procedure Move_Text (Doc : in out Document;
> From : in Documents.Text_Region'Class;
> To : in Documents.Marker'Class) is
> X_From : Text_Region renames Text_Region(From);
> X_To : Marker renames Marker(To);
> ...
>
> I think that's correct. Anyway, those will raise
> Constraint_Error if the parameters are from the wrong
> package.

(BTW, the jargon word is "covariance". Document, Text_Region and Marker are
said "covariant" in Move_Text.)

> However, I consider that to be a workaround (maybe
> others don't think it's that bad), which is why I was
> thinking about making this proposal---to make things
> work more "naturally", without a workaround, in this
> sort of situation that I've run into multiple times.
> I'm not sure what your idea is trying to solve (other
> than "making multiple dispatch perfect"); but even if
> it does make general multiple dispatch available, your
> way of doing things would not solve anything in this
> sort of case, because you would require Move_Text to be
> overridden for every possible combination of children
> of the types, which makes it unusable and means that
> even with your Grand Solution To Everything, those of
> us who want to implement something like the above would
> have to go back to using the workaround.

Consider again ASCII_Text derived from Plain_Text. Let we also derived from
Plain_Text_Region and Plain_Marker:

Plain_Text <-- ASCII_Text
Plain_Text_Region <-- ASCII_Region
Plain_Marker <-- ASCII_Marker

Now, my concern is what happens with Move_To called on

ASCII_Text, Text_Region, Plain_Marker

You say, it is Constraint_Error. The question what is the reason for this?
I don't see any. It is for the programmer to decide.

I you say the language forbids that, I say OK, but then that MUST be done
static.

Anyway your proposal would impose some draconian limitations on the
packages structure. E.g. it would be impossible to provide implementations
and different types of Marker in separate packages. Or consider a generic
implementing a Marker for the given document type. Would that work?

> That's why I think we're not on the same page---we're
> trying to solve two different and unrelated problems
> that seem only superficially related. Maybe we can't
> solve them both.

Actually I considered both cases with the requirement of the constraint
being static. To summarize:

1. Full MD = no constraint => all combinations checked and required
2. SD on tuples = static constraint on the combinations

The case 2 has consequences, of course.

What I find totally inappropriate for a language like Ada is:

3. Dynamic constraint with run-time checks dropping arbitrary exceptions.

I think we should have learnt something from the "accessibility checks
disaster".

--
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de
From: Adam Beneschan on
On Nov 18, 1:46 am, "Dmitry A. Kazakov" <mail...(a)dmitry-kazakov.de>
wrote:

> > It appears to me that we're talking at cross-purposes.
>
> No, it is the same problem of MD. It has some special cases like
> multi-methods, which are simpler, but it is still MD. The example you
> provided is full MD. You have three hierarchies:
>
>    Document'Class, Text_Region'Class, Marker'Class
>
> An operation can be primitive in any combinations of types from these
> hierarchies.

> > Here's an example of the sort of problem I'm thinking
> > about: Suppose you want to define an abstract type that
> > represents a document, which could be a plain ASCII
> > text file, a Word document, a PDF file, etc., that all
> > have in common that they consist of sequences of
> > "characters" and "other elements of some sort"....

> > Of course, Move_Text can't be declared because it is a
> > primitive operation of more than one tagged type.
> > Actually, none of the functions can be declared,
> > either, but I want to focus on the Move_Text procedure.
> > You might want to call Move_Text with a
> > Word_Documents.Document, Word_Documents.Text_Region,
> > and Word_Documents.Marker, or similarly with three
> > objects all with types from the PDF_Documents or
> > Plaintext_Documents package, but you would never want
> > to mix objects from two different packages.
>
> As an example consider these operations:
>
> procedure Cut
>           (  Doc       : in out Document;
>              From      : in Text_Region;
>              Clipboard : in out Document
>           );
> procedure Paste
>           (  Clipboard : in Document;
>              Doc       : in out Document;
>              To        : in Marker
>           );

Right, I wasn't envisioning this sort of operation that involved two
*different* documents of (potentially) two different types. When I
started thinking about this idea, I had had some issues with programs
I was working on, but it was so long ago that I don't remember what
the exact problem was and I can't find it. Whatever it was, it was
*not* a case where there would have been any operations involving two
different objects of two different child types.


> So if you derived ASCII_Text from Plain_Text you would lose Move_Text if
> you forgot to derive from Text_Region and Marker?

Most likely, I would have written the rules so that if you *do*
declare an operation like this of two (or more) different tagged
types, and if in some other package you don't derive from all those
types, it would be an error at that point.

Again, although I can see that someone might want to derive ASCII_Text
from Plain_Text, it wasn't something I considered at the time since it
wasn't germane to the type of problem I was running into.


> Consider again ASCII_Text derived from Plain_Text. Let we also derived from
> Plain_Text_Region and Plain_Marker:
>
>    Plain_Text <-- ASCII_Text
>    Plain_Text_Region <-- ASCII_Region
>    Plain_Marker <-- ASCII_Marker
>
> Now, my concern is what happens with Move_To called on
>
>    ASCII_Text, Text_Region, Plain_Marker
>
> You say, it is Constraint_Error. The question what is the reason for this?
> I don't see any. It is for the programmer to decide.
>
> I you say the language forbids that, I say OK, but then that MUST be done
> static.

I don't see a practical reason why that would be necessary. And I
have a major objection, at least to what I think you're proposing.
Suppose someone at some organization declares a package with some
abstract types. Another organization is developing a large
application. Since this is a large application, it's divided into
several parts with one part being given to one team, another part to
another team, and so on, working independently. The idea is that as
long as each team can develop its part of the application that works
according to some "contract", then you should be able to put the
pieces together and get the whole thing to work. Suppose that two or
three of those teams decide to use this library package and derives
child types from those abstract types. This shouldn't be an issue for
teams working independently, but your idea would make it an issue,
because in order for the program to compile, you would require that
somebody write useless versions of the inherited operations for every
possible combination of derived types, even when the derived types
come from two different teams working independently. Sounds like a
needless burden to me.


> Anyway your proposal would impose some draconian limitations on the
> packages structure. E.g. it would be impossible to provide implementations
> and different types of Marker in separate packages. Or consider a generic
> implementing a Marker for the given document type. Would that work?

1) Keep in mind that I wasn't trying to solve the whole world, just
one subset of the problem. The way I envisioned it would, I think,
have been fairly simple to generate code for and wouldn't be a huge
implementation burden, nor would it have imposed a huge burden on
programmers. (I could be wrong, since there are some cases I didn't
think about, particularly involving tag-indeterminate function
calls.) I realize that my proposal wasn't going to solve everything,
but my feeling is that if you can solve a subset of a problem simply,
and solving the entire problem would be orders of magnitude more
complex, then the fact that there will still be unsolved issues isn't
a valid reason not to solve the narrower problem. (That would be
called "letting the perfect be the enemy of the good enough". And
even with the limitations you think are draconian, I think it would
have been good enough for the types of problems I was encountering.)
Unless we envision that the larger problem *will* be addressed at some
point and the solution to the smaller problem might interfere with the
larger solution. But at the time, I didn't see any reason to believe
that the general "multiple dispatch" case will ever be addressed.
Maybe it still won't.

2) I didn't finish thinking everything through before I abandoned the
idea, so I didn't consider things like generics. Also, it's possible
that there might have been a way to address some of your objections
without significantly adding to the implementation burden.

> What I find totally inappropriate for a language like Ada is:
>
> 3. Dynamic constraint with run-time checks dropping arbitrary exceptions.
>
> I think we should have learnt something from the "accessibility checks
> disaster".

OK, I don't understand this. First, I don't understand what about
accessibility checks was a disaster; and second, I don't see what's
wrong with runtime checks in cases where it's too hard for a compiler
to figure out at compile time whether something will go wrong. Is
this another case of letting the perfect be the enemy of the good
enough?

-- Adam




From: Dmitry A. Kazakov on
On Wed, 18 Nov 2009 08:39:14 -0800 (PST), Adam Beneschan wrote:

> On Nov 18, 1:46�am, "Dmitry A. Kazakov" <mail...(a)dmitry-kazakov.de>
> wrote:
>
> Again, although I can see that someone might want to derive ASCII_Text
> from Plain_Text, it wasn't something I considered at the time since it
> wasn't germane to the type of problem I was running into.

So, in effect you want a depth-1 hierarchy, like we have for the protected
interfaces?

>> Consider again ASCII_Text derived from Plain_Text. Let we also derived from
>> Plain_Text_Region and Plain_Marker:
>>
>> � �Plain_Text <-- ASCII_Text
>> � �Plain_Text_Region <-- ASCII_Region
>> � �Plain_Marker <-- ASCII_Marker
>>
>> Now, my concern is what happens with Move_To called on
>>
>> � �ASCII_Text, Text_Region, Plain_Marker
>>
>> You say, it is Constraint_Error. The question what is the reason for this?
>> I don't see any. It is for the programmer to decide.
>>
>> I you say the language forbids that, I say OK, but then that MUST be done
>> static.
>
> I don't see a practical reason why that would be necessary. And I
> have a major objection, at least to what I think you're proposing.
> Suppose someone at some organization declares a package with some
> abstract types. Another organization is developing a large
> application. Since this is a large application, it's divided into
> several parts with one part being given to one team, another part to
> another team, and so on, working independently. The idea is that as
> long as each team can develop its part of the application that works
> according to some "contract", then you should be able to put the
> pieces together and get the whole thing to work. Suppose that two or
> three of those teams decide to use this library package and derives
> child types from those abstract types. This shouldn't be an issue for
> teams working independently, but your idea would make it an issue,
> because in order for the program to compile, you would require that
> somebody write useless versions of the inherited operations for every
> possible combination of derived types, even when the derived types
> come from two different teams working independently. Sounds like a
> needless burden to me.

No, it is not a burden it is a mere consequence of a decision made earlier.
If the abstract types are Printer and Contents with the joint operation
Print (the classic example of MD), you *have* to implement all
combinations. It is not a question. The question is how to make the
language helping us in doing this work safely and efficiently.

I have no idea how to do this while keeping it modular. But that does not
change the fact that all combinations have to be defined. To silently
define some of them as Constraint_Error is a very bad idea for the language
like Ada.

>> What I find totally inappropriate for a language like Ada is:
>>
>> 3. Dynamic constraint with run-time checks dropping arbitrary exceptions.
>>
>> I think we should have learnt something from the "accessibility checks
>> disaster".
>
> OK, I don't understand this. First, I don't understand what about
> accessibility checks was a disaster;

Because they are the major contributor to hours spent on debugging
unhandled exceptions.

> and second, I don't see what's
> wrong with runtime checks in cases where it's too hard for a compiler
> to figure out at compile time whether something will go wrong.

Accessibility checks are known for being false positive. Same with MD, it
is not a semantic error to cross types in an operation. It is an
*artificial* error introduced by the language designer, because it would be
too difficult to do it otherwise (e.g. right (:-)). Then the very same
designer finds his own error too difficult to detect at compile time! I
have no problem with the former, but do not accept the latter.

> Is
> this another case of letting the perfect be the enemy of the good
> enough?

There exist lots of imperfect languages already. But Ada must be perfect!
(:-))

Returning to the case where we do not want cross combinations. I thought
about it and came to the conclusion that this is single dispatch (tags are
synchronous). I think we should approach this differently.

Let us consider an example were dispatching table is semantically
"diagonal":

type Object is limited interface ...;
type Handle is interface ...;

Each time we derive from Object, we want a new Handle. This is IMO a better
example than Document x Region x Marker.

Note that here the issue of packages is especially important. Most likely
we wanted to place Objects into private packages, making only Handles
public.

Most operations on Object and Handle are same and have only one controlled
argument. I am tempted to say that Handle should also implement Object.

type Handle is interface and Object ...;

But there are two cross operations:

function Ref (X : Object) return Handle is abstract;
function Target (X : Handle) return access Object is abstract;

The same problem more complicated. How to add

type Readonly_Handle is interface ...;

--
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de
From: Randy Brukardt on
"Dmitry A. Kazakov" <mailbox(a)dmitry-kazakov.de> wrote in message
news:1wtsriaxu0s4s$.ikwnnz5teukp$.dlg(a)40tude.net...
....
>> OK, I don't understand this. First, I don't understand what about
>> accessibility checks was a disaster;
>
> Because they are the major contributor to hours spent on debugging
> unhandled exceptions.

That seems odd to me. I rather *like* getting unhandled exceptions, because
it is almost always easy to see what the problem is from the exception name
and the traceback. (And all of my long-running programs have systems to
record this in the case of an unexpected exception.) It's the incorrect
results, compiler bugs (where the code is right, but the wrong thing
happens), and crashes that cause "hours of debugging".

OTOH, doing something that even generates a runtime accessibility check is a
bug IMHO (it's what Bob Duff calls a "tripping hazard" - a latent problem
that will bite you when someone does something unconventional -- in that
sense it is just like the bug of assigning a string parameter has lower
bound 1); it would be useful if the compiler could optionally point out such
places so you could fix them.

Randy.