<html>
<head>
<style>
.hmmessage P
{
margin:0px;
padding:0px
}
body.hmmessage
{
FONT-SIZE: 10pt;
FONT-FAMILY:Tahoma
}
</style>
</head>
<body class='hmmessage'>Rodney, thank you, this is interesting.<BR>
I definitely don't want to pay for heap allocation for a tiny array.<BR>
I don't know about "subarray". It looks like it takes and returns arrays. It's not a type. I ordered another copy of the Nelson book so I don't have to find mine.<BR>
 <BR>
Good idea "MakeT" I forgot about that pattern. I'll try it out.<BR>
 <BR>
The record and array I propose are not all that different really.<BR>
I just heard of something new. Have you heard of it? "Duck typing". If it acts/quacks/walks like a duck, it is a duck.<BR>
This is in very dynamic languages like Ruby.<BR>
You apply object.method and if object defines something named "method", then it "must" have "the" meaning you intend.<BR>
Kind of like how C++ templates "accept as parameters whatever happens to work".<BR>
 <BR>
Operator overloading is great for strings and "math".<BR>
 <BR>
Maybe I should try to have this language debate from scratch again..?<BR>
 <BR>
I still am conflcted.<BR>
 <BR>
Modules seem overly heavyweight.<BR>
I don't want Module1.T, Module2.<FONT face="">T</FONT>, I want T1, T2.<BR>
 <BR>
C++ stack structs with non virtual member functions:<BR>
class Rect_t<BR>
{<BR>
  Rect_t() : top(0), left(0), right(0), bottom(0) { }<BR>
 <BR>
   int Height() { return bottom - top; }<BR>
   int Width() { return right - left; }<BR>
   int top, left, bottom, right;<BR>
};<BR>
 <BR>
seems "good".<BR>
 <BR>
And it seems not really all that complicated for the compiler to flow the static type information around to resolve the functions..<BR>
 <BR>
Rect_t r;<BR>
<FONT face="">r.Height</FONT>() => Rect_Height(&r); ..and would be inlined anyway.<BR>
 <BR>
I do find some compelling features in Modula-3. Mainly that it compiles to native code and has OPTIONAL safety, optional garbage collection, and that the syntax of modules/interfaces allows fast compilation -- no longer reparsing the same headers over and over and over and over.<BR>
 <BR>
Operator overloading btw..have seen "template SafeInt"? It acts like a primitive integer, but raises exceptions upon overflow.<BR>
For this to work very much requires operator overloading.<BR>
 <BR>
A point, of course, is to be able to have user defined types that can act like the built in types..<BR>
 <BR>
 - Jay<BR><BR>

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