[M3devel] small array in modula-3?

Darko darko at darko.org
Fri Nov 16 05:15:27 CET 2007


Is it really four words? I would have thought it might need a type  
reference and a size, what are the others for?


On 15/11/2007, at 4:39 PM, Rodney M. Bates wrote:

> Jay wrote:
>
> > What is the right way to have a variably sized but always small  
> array in Modula-3?
> > My array will only ever have 1 or 2 elements.
> > I'd like to always allocate room for 2 elements, and have there  
> be a size.
> >
> > It seems I have a choice of
> >
> > a) an "open" array
>
> Heap allocated, I presume?  If the max size is only 2 elements,
> this is pretty extravagant, as a heap allocated open array will
> have 4 extra behind-the-scenes words of space overhead, plus
> maybe heap fragmentation, and time overhead of allocation,
> collection, and maybe reduced locality of reference.
>
> > b) wrap it up in a record
> >
> > I'd like so have, like:
> >
> > TYPE A = ARRAY [0..1] OF FOO;
> >
> > And be able to say:
> >
> > VAR
> >  a : A;
> >
> >  ..
> >  a.size
> >  FOR i := 0 TO a.size DO
> >    do something with a[i]
> >
> > It seems I have no option but, like:
> >
> > TYPE A = RECORD
> >   a: ARRAY[0..1] OF FOO;
> >   size := 1; (* usually of size 1, sometimes 2 *)
> > END
> >
> > and then
> >  FOR i := 0 TO a.size DO
> >   do something with a.a[i];
> >
> > That is "ok". Not great -- what to call the inner a?
> > But then furthermore, I'd like to construct constants.
> > It seems I am stuck with either the verbose:
> >
> > PROCEDURE F(a:A);
> >
> > F( A { ARRAY[0..1] OF FOO { .. } );
> >
> > OR I have to come up with a name for the embedded array.
> > But of course, its type is really "the same" as the outer type.
>
>
> Ignoring the fact that the types are different linguistically
> (one a record type, the other an array), the types are different
> at a deep semantic level too.  The inner array has static
> size, the outer one (call it a "variable array", perhaps)
> has dynamically changeable size, even more easily changed
> after it is created than a heap-allocated open array.  This
> is a significant semantic difference, so it also makes program
> design sense to view them as different types.
>
> >
> > To wit:
> >
> > TYPE FooArray = ARRAY[0..1] OF Foo;
> >
> > TYPE FooArray = RECORD
> >   a : FooArray;
> >   size := 1;
> > END;
> >
> > F( FooArray { FooArray { .. } );
> >
> > But I have to come up with different names.
> >
> > And I don't think I can leave out the name for the constructor,  
> like:
> >
> > F( FooArray { { .. } );
>
>
> Yes, this is a limitation in Modula-3.  Ada allows value constructors
> to omit inner type names in cases like this, and it is convenient.   
> But
> it also crosses a really major line on complexity of the language  
> semantics,
> since type analysis information now flows not only upward, but also  
> downward
> in expression typing.  I am mostly content to live with this as one  
> bit of
> the price of avoiding a horribly over complex language.
>
> Ordinary procedures can do pretty much all of the things done by  
> exotic
> and complex language stuff like C++ constructors.  If you don't  
> want to write
> the ponderous nested value constructor, write a constructor  
> procedure and
> call it.  As Antony suggested, you can make it accept an open array  
> formal,
> which then codes just like a simple array value constructor.  You  
> could even
> make it elaborate and general, e.g.:
>
> PROCEDURE MakeF ( Val : ARRAY OF FOO ) : F
>
> = VAR LSize : CARDINAL
> ; VAR LResult : A
>
> ; BEGIN
>     LSize := NUMBER ( Val )
>     <* ASSERT LSize <= NUMBER ( FooArray ) *>
>   ; LResult . size := LSize
>   ; SUBARRAY ( LResult . a , 0 , LSize )
>       := SUBARRAY ( Val , FIRST ( Val ) , LSize )
>   ; RETURN LResult
>   END MakeF
>
> Alternatively, since your maximum element count is so small, you could
> write a constructor procedure that took two formals of type FOO, with
> at least the second one optional.  (This would require a distinguished
> value of type FOO that would be used to mean "omitted".)
>
> And, of course, if you want to use abstraction, you can put the types,
> constructor procedures, and various other procedures for manipulating
> the variable sized array in a module, behind an interface.
>
> An additional limitation of Modula-3 in this regard, is that you can't
> make the type F opaque, unless you heap allocate it, which we were  
> trying
> to avoid.  Ada would allow you to do this, but it's another example of
> a convenience with high cost.  It forces the equivalent of the  
> revelation
> to be located in the equivalent of the interface, but makes it illegal
> to write client code that depends on what the revelation is.
>
> This in turn creates a source code control nightmare in a large  
> project,
> because now someone who wants to make what is really a purely  
> internal,
> implementation change, nevertheless has to check out the interface,  
> and
> if you aren't in denial mode, that means implementers of all the  
> client
> code have to go to extra trouble to somehow find out that what appears
> to be an interface change actually doesn't affect them after all.
>
> >
> > Though that might seem nice.
> >
> > Am I understanding everything?
> >
> > Have folks hit this before and there's a set of names that don't  
> seem too lame
> > that folks use?
> >
> > Also -- language documentation?
> > Nelson's green book is excellent.
> > The stuff in the doc directory is very dry and scientific.
> > The tutorial seems more like a reference. Or maybe I didn't read  
> it enough.
> > Is there better, in case I need a refresher?
> > I think I got it, via Nelson's book from memory (wonder if I can  
> find mine..) and the reference,
> > but I don't think anyone could learn from the current online docs  
> in the source tree.
> >
> > Maybe it's me, some combination of laziness and short attention span
> >  as I age..
> >
> > Btw, C doesn't offer a great solution here, though it offers  
> leaving out some type names.
> > In C++ I could have both .size and operator[].
> > Modula-3 seems to be missing operator overloading.
> > It's got some builtin stuff, even array assignment and equality  
> and I think
> >   even record assignment and equality, but it is still a bit  
> limiting.
>
>
> I have raved on this before, but, having had lots of painful  
> experience with
> user-defined overloading in Ada and C++, I can say with authority,  
> that it is
> a programming language disaster.  It interacts with just about  
> everything
> else in the language, in very complicated ways, and all it buys you  
> is saving
> time/energy thinking up distinct names for procedures/functions.   
> Even this,
> aside from the effects on the language, is a net loss, by the time  
> you consider
> readability along with writability.
>
> User-defined overloaded operators provide a slight readability  
> benefit, _if_
> used with great restraint and discipline, something you can rely on  
> not happening.
> Meanwhile, the language complexity can easily double or worse.   
> And, with the
> exception of compiler writers and language lawyers who spend  
> hundreds of hours
> on just this, programmers don't understand the rules, not even close.
>
> >
> > Also, if I understand things correctly, this has long bothered me  
> about Modula-3,
> >  though I'm more tolerant now -- Modula-3 doesn't seem to allow  
> for lighter wieght
> >  objects. Like, small stack allocated structs with member  
> functions. You seem to have
> >  to chose between heap allocated garbage collected virtual member  
> functions full
> >  featured objects, or featureless dumb structs. It's nice how C++  
> allow hybrids --
> >  objects don't have to be heap allocated and member functions  
> don't have be virtual.
> >  Or am I missing something?
>
>
> C++'s supposedly lighter weight forms of classes/structs with their  
> special
> member functions buy nothing that plain records, plain procedures, and
> interfaces/modules don't already provide, again, at significant and  
> gratuitous
> language complexity.  Except when methods/member functions actually  
> dispatch
> dynamically, there is nothing that the above won't do, and when you  
> create a
> class instance as a local variable (i.e., on the stack), it is  
> necessarily
> not polymorphic, that is, it can't change its "allocated" or  
> dynamic type
> among various subtypes at runtime.  This in turn means it can't  
> dispatch.
>
> So, just use plain procedures, an interface and a module, and you  
> will get
> everything a lighter-weight C++ class would give you.
>
>
> >
> > Anyway, I've gotten to accept C a bit more vs. C++ so I can deal  
> with
> > t: Type;
> > Type_DoSomething(t);
> >
> > in place of:
> > t.DoSomething();
>
>
> Exactly.  The special "receiver object" in a true method call has  
> significant
> semantic differences from an ordinary parameter and introduces new  
> complexities
> and non-orthogonalities.  It has some very valuable uses too.
>
> But to then create degenerate forms of it that still carry a lot of  
> these
> complexities, but are equivalent in programing power to plain old
> parameters is just bad program design and bad language design.   
> Objects and
> methods are indeed cool for situations that utilize their semantic  
> complexity.
> But it's deeply uncool to try to look superficially cool by using an
> inappropriately sophisticated construct when the problem doesn't  
> justify it.
> Some OO proponents have gone way over the deep end here.
>
> >
> >  - Jay
> >
> >
> >  
> ---------------------------------------------------------------------- 
> --
> > Boo! Scare away worms, viruses and so much more! Try Windows Live  
> OneCare! Try now! <http://onecare.live.com/standard/en-us/purchase/ 
> trial.aspx?s_cid=wl_hotmailnews>
>
>
> -- 
> -------------------------------------------------------------
> Rodney M. Bates, retired assistant professor
> Dept. of Computer Science, Wichita State University
> Wichita, KS 67260-0083
> 316-978-3922
> rodney.bates at wichita.edu
>
> -- 
> -------------------------------------------------------------
> Rodney M. Bates, retired assistant professor
> Dept. of Computer Science, Wichita State University
> Wichita, KS 67260-0083
> 316-978-3922
> rodney.bates at wichita.edu




More information about the M3devel mailing list