[M3devel] declaring/initializing variables "anywhere"

Jay jay.krell at cornell.edu
Tue Aug 4 20:07:54 CEST 2015


But...Modula-3 already has this in VAR and WITH.

Every language has this for temporaries:

F1(F2() + F3())

Are these bad?

Too much explicit detail can actually get in the way of reading the code.


People also claim "just hover over the variable in IDE or debugger" which I don't buy. The tools always lag the language -- even if some don't, old tools remain in use.


"instant gratification" is also spun as "productivity" and "automatic maintenance" -- don't need to adjust redundant type declarations when things change, assuming compiler gets it right. Some people trust the deduction more than human, some don't.


 - Jay

On Aug 4, 2015, at 9:42 AM, "Rodney M. Bates" <rodney_bates at lcwb.coop> wrote:

> You're poking at a really big peeve of mine.  I do a lot of maintenance work.  It usually
> involves finding one's way around in hundreds of thousands of lines of unfamiliar code.
> If you're exceptionally lucky, an eventual one-line change can be figured out after vetting
> a mere several tens of lines.  Very often, it is more like a few hundreds, and not
> infrequently, even more.
> 
> The average line of actively maintained code is written once and read something like
> seven times.  (I don't remember where that number came from.)  Speaking for myself,
> even most brand new code gets read at least seven times before it gets past my own testing,
> before it gets passed to anybody else to either use or further test.  Moreover, the initial
> writer already has lots of context in his head that a maintainer has to ferret out.
> 
> What I am leading to is that things should be *locally explicit*, far more than we usually
> see.  Saving keystrokes once at initial writing time, at the cost of forcing the poor wretches
> who have to come along and figure it out later to constantly locate, open, scan another
> source file, every fourth token they read, is penny wise and pound foolish.  It's classic
> case of instant-gratification immaturity.  Ensuring a ton of aggravation later, to
> save an ounce of effort now.  It's just plain laziness.
> 
> (more below:)
> 
> On 08/04/2015 05:02 AM, Jay K wrote:
>> I had:
>> 
>> 
>> PROCEDURE CompileProcAllocateJmpbufs (p: Proc) =
>> VAR module := Module.Current ();
>>     alloca := Module.GetAlloca (module);
>>     size := Module.GetJmpbufSize (module);
> 
> So, coded like this, the poor schmuck who has to come along and figure this
> out will have to find Module.i3 and search it for declarations of Current,
> GetAlloca, and GetJmpbufSize, just to know what types we have.  And possibly
> more steps, as with alloca, whose type, as we will find out, requires
> going to yet another source file CG.i3.  It can be even worse, e.g.:
> 
>  VAR V := Ptr^.Field[I].method(X);
> 
> You have to track down the type of Ptr, to find Field, to find the type of
> its elements, to find method, to find its result type.
> 
> Sometimes it's obvious from identifier names, but more often, it is not, or at
> least only too vaguely for serious software work.  Is a module denoted by an
> abstract type?  An integer numbering of modules?  something else?  Very often,
> there are two or three different types that denote a module or whatever.
> 
> (An aside:  In C++, things often get dramatically worse when coders, overly
> enamored with cleverness for its own sake, define implicit type conversions
> among these, so the poor maintainer has even less idea what is going on.
> Moreover, the conversions could be declared anywhere in the tens of transitively
> #included files, and there is no path leading to them, only exhaustive search
> through all the files.  And this possibility has to be considered for every
> single assignment and actual parameter.)
> 
> Instead, I always code cases like this by putting both the type and the initializer
> in the declaration:
>  VAR module : Module.T := Module.Current ();
> 
> I even often do it this way when the initializer is a literal.  For one thing,
> I may want a subrange for the type of the variable.
> 
> The exception is when the initializer itself also names the type.  It's shorter,
> but at no loss of explicitness.
> 
>  VAR rec := SomeInterface.SomeType { 0 , NIL , FALSE };
> 
>>     try_count := p.try_count;
>> BEGIN
>> 
>> 
>> which is fairly nice and elegant.
>> I like the static type inference.
>> 
>> 
>> but p could be NIL so I need like:
>> 
>> 
>> PROCEDURE CompileProcAllocateJmpbufs (p: Proc) =
>> VAR module: Module.T;
>>     alloca: CG.Proc;
>>     size: CG.Var;
>>     try_count: INTEGER;
>> BEGIN
>>     IF p = NIL THEN RETURN END;
>>     module := Module.Current ();
>>     alloca := Module.GetAlloca (module);
>>     size := Module.GetJmpbufSize (module);
>>     try_count := p.try_count;
>> 
>> 
>> double the lines, and a need to state types that I didn't have to state before,
> 
> This will save wasted computation calling the functions, if it turns out p=NIL.
> Depending on the purpose of the code.  In some code, I care about efficiency
> at this level.
> 
>> 
>> OR I can use WITH to get the "best" of both, but implied extra indentation.
> 
> If I were to propose any language change at all, it would be to allow a WITH
> binding to optionally specify the type too, for exactly the same reasons.
> 
>  WITH w : T = Var.method(x) DO ...
> 
> Many a WITH statement has been far too hard to read, requiring the side trips of
> checking other source files to see what this value really is.
> 
> 
> 
>> 
>> 
>> Pretty much all other mainstream languages in use today,
>> except C89, are "better" than this, they all let you
>> both delay local variable declaration until arbitrarily
>> into a function, but with implying that you should indent further,
>> or close an extra block.
> 
> To be clear, I definitely do not advocate allowing declarations and statements
> to be arbitrarily mixed in a block, BUT...  if we did it, at least the decls
> would be syntactically explicit with a VAR, and we would not have to "define"
> our language with words like "if it looks like a declaration...".
> 
>> 
>> Most mainstream languages also share Modula-3's type inference
>> and let you omit the type, except C.
>> 
>> 
>> Can we update Modula-3 here somehow?
>> 
>> 
>> Or just use "with"?
>> 
>> 
>> Proposals for a syntax that works well with the existing language and compiler?
>> 
>> 
>> Thank you,
>>  - Jay
>> 
>> 
>> 
>> 
>> _______________________________________________
>> M3devel mailing list
>> M3devel at elegosoft.com
>> https://mail.elegosoft.com/cgi-bin/mailman/listinfo/m3devel
> 
> -- 
> Rodney Bates
> rodney.m.bates at acm.org



More information about the M3devel mailing list