[M3devel] small objects

Mika Nystrom mika at async.caltech.edu
Fri Apr 10 21:02:07 CEST 2009


Specific proposal.

What Rodney said, *except* make REFANY the root of everything.
Insert an untagged root with a new name.

Rodney himself has said that the uses of REFANY he knows about would
be changed to accept the TAGGED type, so I simply propose allowing
REFANY to handle the TAGGED type by default, and insert a new root
for the untagged types.  The structure of the type hierarchy is
exactly the same as in Rodney's proposal, but the different naming
makes it more backward-compatible.

ROOT <: UNTAGGEDREFANY
T <: UNTAGGEDREFANY

UNTAGGEDREFANY <: REFANY

and finally.

TAGGED T <: REFANY (* for all T *)

The advantages with this proposal are that it does precisely what
Rodney is asking for (typesafe ADTs), but it's compatible with 
Tony's runtime changes in the *current* M3 implementation and it
won't require anyone to do a massive search and replace, replacing
REFANY with "TAGGED REFANY" in every existing Modula-3 program.

Supposed disadvantage: every TYPECASE, NARROW, etc., of REFANY will
cost an extra LSB check.  Those who feel strongly about that and
for some reason *know* that they don't want to process TAGGED types
(which may be the empty set), can modify their code to use
UNTAGGEDREFANY instead of REFANY.

     Mika

"Rodney M. Bates" writes:
>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