[M3devel] small objects

Tony Hosking hosking at cs.purdue.edu
Sat Apr 11 00:25:32 CEST 2009


Too many e-mails to digest lately.  I take it that Mika's is now  
definitive.  Let me think it through.

On 11 Apr 2009, at 05:18, Mika Nystrom wrote:

>
> Sigh, I hate sending so many emails to a mailing list.  Sorry about
> the inboxes I'm clogging of people with no interest in this.
>
> But I just realized something important, which I think may be
> decisive in deciding the fate of the name "REFANY" in the addition
> of new types.
>
> Rodney proposes
>
> TAGGED T <: TAGGED REFANY
> T <: REFANY <: TAGGED REFANY
>
> I propose
>
> TAGGED T <: REFANY
> T <: UNTAGGEDREFANY <: REFANY
>
> Both proposals are identical in the power of the language that
> results, because they differ merely in naming.
>
> Both proposals are also backward-compatible: all existing Modula-3
> programs are unchanged by them.
>
> However, UNTAGGEDREFANY (mine), is *forward*-compatible as well
> as backward-compatible.
>
> Think about it.  The TAGGED REFANY proposal will have the following
> effect: people will go through all the M3 libraries and replace
> every or almost every occurrence of REFANY with TAGGED REFANY.  The
> resulting code will not compile with an older compiler!
>
> In my proposal, it is the user of the TAGGED types who is responsible
> for---in new code only!---deciding whether he wants his code to
> compile both on older and newer M3 systems.  If he does, then he
> can add appropriate implementations for compilers that don't support
> the TAGGED types (which will be trivial since he has to have those
> anyway!)  The burden of handling change is on the programmer of the
> special new feature rather than on everyone who has a container
> module.
>
> I'll try to refrain from posting any more messages on this topic now.
>
>     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