procedure foo(i : integer)
var i : integer = 1;
procedure bar(j : integer)
i := i + 1;
j := j + 1
end
bar(i);
print(i)
end
What is printed?
I wondered if there was a sensible answer.
Hopefully the compiler would give a warning "Do you really want to create a local variable the same name as a passed parameter?" at line 2.
If that warning is ignored, then does procedure bar inherit the current instantiation of i from foo due to scoping?
if not, then compiler should warn "uninitiated variable i"
if so within bar, i := i + 1; will operate on the i declared in foo due to scoping: i then = 2
j := j + 1 will operate on the i declared in foo as a passed variable by reference: i then = 3
Print 3
This seems logical to me. Makes what I regard as sensible interpretation of scoping. Is this a reasonable analysis? other interpretation?
Maybe a solution is to make the rules flexible [procedure bar(i) - don't say how i is passed and let the linker make that decision. Not the same as VB where the variable is mutable at run time, just flexible until link time]. If the procedure caller doesn't care what happens to the passed variables or requires their version to remain unchanged, can explicitly pass by value. If the procedure caller expects something to be modified and wants the result, explicitly pass by reference. Let the linker fix it up. This means the programmer has more flexibility, the procedure writer can determine if a particular method is required (causing a linker error if not adhered to) or let the linker fix it. And there is no ambiguity in the calling code.
Very good except our friend stated "So 'pass by reference' here is meant to indicate that the callee can change something in the datum that's been passed", and in other places that it might not actually be by a pointer, but by being passed in a register and passed back. He's also indicated several times the he follows Ada in various things.
Ada has INOUT parameters, where it is *undefined* whether they are passed by copy/return or by pointer.
This makes a difference to code such as the above.
A similar discussion arises when we discuss stuff like:
for (I = 0; I < Funct(I); I++)
{
;
}
Is
Funct(I) evaluated once, at loop initialization and the value stored opaquely? or is
Funct(I) evaluated at the start of each iteration?
There is no
right answer, these are options that a language designer must weigh up and choose.
Given the prevalence of passing structures in C on MCUs as almost always by address, it makes sense to recognize that and why it happens and then say "OK, well since whenever we pass a structure into some function in C on say STM32 devices, we always pass its address for the performance gain and because the callee will likely update the structure, lets recognize that and relieve the developer from having to always pass a pointer or pass the address".
We could even declare the datum itself with a "pass as" attribute, is that a good or bad idea? That way we can declare some structure to some concept like an A/D Converter as inherently always passed by val or ref, then there is no pass by convention, instead the means of passing is part of the type...just sayin...I've not thought about this at all, just throwing it out there, suggest, propose ideas, first, evaluate their utility later...I love ideas, I do not defer to orthodoxy, instead I like to hear all ideas, whether they be good or bad doesn't matter at first, we can always decide that later, this is lateral thinking, think freely, worry not, just generate ideas, encourage the breaking of convention, suggest the absurd even, but do not filter human thought prematurely, this is the essence of western European rationalism, the scientific revolution, there's nothing to worry about, get hung up about, this is just a discussion on the interet.
That's all I'm saying, sure, one can write code that abuses that or does it in a way that seems to undermine the principle, but we can do that with any language, one can take any language and write appalling code and then say "Look, I told you, that's a crap language".