[Oberon] R: Should one automatically initalize local pointer or procedure variables (safety precaution)?
Till Oliver Knoll
till.oliver.knoll at gmail.com
Wed Mar 6 09:08:51 CET 2019
> Am 05.03.2019 um 15:32 schrieb Skulski, Wojciech <skulski at pas.rochester.edu>:
>> Not only against „hidden features“, but also against the strict declare-initialise-use paradigm emphasised by Niklaus Wirth ;)
> If one has NW discipline then one is going to write perfect code no matter what. But not everyone has such a discipline.
Well, I‘d say that‘s /exactly/ the purpose of a well-designed programming language: to „force“ people into discipline and to take on „good programming practises“ ;)
The removal of the „return“ statement in Oberon-07 is such an example: while I admit that I‘ve used it too, the occasional „bail out early (when some precondition not met)“-return statement at the very beginning of some function, it usually makes the code less readable it most cases (to say the least). In the worst case you‘re missing some important piece of code at the very end of the function, leaking resources etc.
Now Oberon-07 simply forces you to abandon this „bad habit“.
Not to mention its rigorous type-safety.
As a side-note: have you ever tried Python? It simply did not grok well for me (even though I /wanted/ it to be cool): „Uh... is the input ‚actor‘ now supposed to be some string, some ID or what the hell? Where‘s the API docu again?“ and yes, in my concrete example of some „PLEX“ („media library/player“) it was indeed a string. But of course not some plain vanilla Python string, but some PLEX-specific string (because of some Unicode-related issues or what do I care): of course you only learn about this at runtime, and only if you‘re lucky, because Python manages to convert „everything into everything“.
Same with Python, as it now at least provides /optional/ type-checking at compile-time...
But I was drifting off a bit ...
Anyway, I agree that it is a thin line between „annoying seasoned programmers with safety features“ and „constantly slapping on Joe Programmer‘s hands when he‘s trying to pull of some quick and dirty job“...
But IMHO nicely designed languages always help you in writing better code, without annoying you too much, as most seasoned developers would naturally apply those programming practises anyway, even when not forced too.
>> And also somewhat against „locality of code“, as you should „initialise your variables as late as possible (but not later)“, or in other words: initialisation should happen as close as possible to actual use (e.g. right before some loop).
> Definitely the case with index variables. But here we are discussing pointers. How often do you use a pointer to index a loop? It is not even possible. List traversal is a sort of the loop and Stefano's example is a good one. So one has to weigh a minor optimization (avoidance of automatic pointer initialization) versus improved safety. I heard more than once that safety should go first.
Oh, my wrong: I came late to the party and did not realise we were /specifically/ talking about pointers.
But basically my same arguments apply: so apparently the goal here is to make the application crash as soon as some „uninitialised“ (not explicitly initialised in the code) pointer is accessed.
I agree that this would certainly be useful in order to detect exactly those uninitialised pointers during development time, e.g. implicitly initialise all pointers to some non-existing/forbidden address (e.g. NIL or 0xFFFFFFFF or whatever) in „debug mode“ (if there was such a thing in the Oberon compiler). I think certain C++ compilers do exactly that.
This would make sure that an otherwise non-initialised „random pointer“ could accidentally point to some „valid“ address (which only later triggers an error).
But IMHO this should /not/ be a regular „language feature“. Why? Well, if you start implicitly initialising all pointers to, say, NIL (= some well-defined default value): why then not for INTEGERs and BOOLEANs? How are you going to explain the „why“ behind this to students? To seasoned developers, for that matter?
And is it now intentional or a simple omission if you read code like:
p: POINTER TO ...
(* other code, possibly fiddling with p *)
WHILE p = NIL LOOP ...
And why not write that extra line of code which makes your intentions crystal?
p := NIL;
WHILE p = NIL LOOP ...
Even though if your intentions are for „code safety“, if you make it a language feature that pointers are initially NIL people /will/ „exploit“ that, as illustrated above.
So IMHO a good „debug feature“, but „should not be a language feature“.
> So my taste, experience, and belief makes me vote for automatic pointer initialization, possibly optional and turned on/off with a switch.
Like with a „debug switch“ ;)
My 2 cents anyway.
More information about the Oberon