[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