[M3devel] small objects

Rodney M. Bates rodney.m.bates at cox.net
Fri Apr 10 19:24:49 CEST 2009


Mika Nystrom wrote:
> Sorry to splice together two emails from you, but I feel I've already
> used up my m3devel quota this week:
>
> "Rodney M. Bates" writes:
>   
>>> Are you sure?  I want a type---some type---that can hold "any
>>> reference, even a tagged one", and I would rewrite most library
>>> code that today takes REFANY to take that instead.  Why not?  Why
>>> would I want to limit it to REFANY when it performs no operations
>>> that couldn't legally be performed on TAGGED REFANY.
>>>
>>>       
>> I believe my "safe" proposal would make this very simple, if I am
>> thinking of the kind of library code you are.
>>  
>> I envision a container data structure that takes in things and returns
>> them without performing operations on them other than moving them around
>> and storing them, e.g. the ever belabored stack.   The values going in
>> and out are declared REFANY, and the client passes in values of
>> some proper subtype of REFANY, which get assigned to the REFANY
>> parameters.   When it gets them back, it narrows them to this type.   
>>
>> In this pattern, just changing the declared type of the container values
>>     
> >from REFANY to TAGGED REFANY would do it.  The library code's storage
> ...
>   
There are two very different kinds of uses of reference and
tagged types.  The one I speak of above is for the type of the
elements inside a container data structure.  In this case, it
is the client that knows what type the value really is, and will
declare it as such.  The library ADT module should know as little
as possible about it, so it will declare it as REFANY or
TAGGED REFANY.   Here, you want the  most general type
possible,  just to make the abstraction more versatile.  
And TAGGED REFANY  generalizes it from  REFANY.  

But...
>   


>>> you'd like to store these in a REFANY and dynamically test for the 
>>> appropriate tagged type:
>>>       
>> No, I do not want to store these in a variable of type REFANY or any 
>> other existing type. 
>> In fact, I want to forbid it.
>>     
>
> I think you are thinking of exactly the same kind of library code.
> TextRefTbl.T, RefList.T, etc.
>
> After the introduction of TAGGED REFANY, what use is there for
> REFANY?  What piece of code can you think of where the cost of the
> 1-LSB check of TAGGED REFANY outweighs the convenience of being
> able to process objects of type TAGGED T (for all ref types T) as
> well as objects of type T?
>   
The other use is for the abstract type itself.  Forgetting tagged
types for a moment, I have never seen an interface/module that
uses REFANY for this.   Instead, the modules declare their abstract
type as some proper subtype of REFANY, usually an opaque type.

It would be possible to use just REFANY here of course, but that would
require an otherwise unnecessary RT check on the allocated type,
every time an operation of the module is called.  This is a much
more expensive check than a tag check, as has been pointed out
in this discussion.  

But worse, it would sacrifice the static checking that we now have
that prevents, at compile time, clients  from passing, say a Text.T
to some procedure in Atom that expects an Atom.T.  If these modules
ever wanted to use a tagged type, but the only tagged type were
REFANY, we would lose this static checking, because Text.T would
have to become equal to Atom.T.

In cases where your algorithms don't specifically need dynamic
typing, static typing is always much better, because one run of
the compiler on the source code will do it.  Bugs checked
only at runtime require a massive test suit to be coded and then
regularly rerun to get even close to the same confidence they've
been found.

So when using tagged types as the ADT itself,, we need to be able
to have a tagged version of whatever proper subtype of REFANY
the abstraction needs, including an opaque subtype of REFANY
or an opaque subtype of some Public subtype of REFANY.  This is
why I am adamant that we need to be able to build a tagged type
from any traced or object type. 

And once you do this, keeping REFANY itself unchanged and allowing
TAGGED REFANY as one case of a tagged type falls out of the system
for free _and_ saves a lot of cases that would otherwise need a new RT
check that can never fail, but the language can't know that, because
the type system has lost the distinction.

I really feel that the fad of all dynamic typing in languages is a huge
mistake and that it will someday be recognized as such.  In the
meantime, we have a language that provides a very extensive set
of statically-typed alternatives, while also allowing dynamic typing
when you really need it.  This is one of Modula-3's best principles. 
Let's don't erode the static alternatives unnecessarily.

>     Mika
>
>   




More information about the M3devel mailing list