I believe this would be a nice feature. It would make programs that use it more self documenting and, it would also probably make future automatic translation of MS headers a bit simpler and more likely to be correct.I see no reason to add something like this. It complicates the language and adds a new keyword with no real gain.
Here is the reason: if the compiler knows that the variable is inout then it can emit a hint (or warning) if an uninitialized variable is passed to the function or procedure.I believe this would be a nice feature. It would make programs that use it more self documenting and, it would also probably make future automatic translation of MS headers a bit simpler and more likely to be correct.I see no reason to add something like this. It complicates the language and adds a new keyword with no real gain.
That macro causes the compiler to give a warning if the variable being passed to the function/procedure has not been initialized ?... what version of FPC are you using ?... that's a nice macro you got.But I find it syntax rot. The meaning of var is clear. OTOH, this macro does what you want.
{$macro on}{$define inout:=var} procedure test(inout value:integer); begin end; begin end.
This is done by var already. There is no reason to add a new keyword for something that already exists.Here is the reason: if the compiler knows that the variable is inout then it can emit a hint (or warning) if an uninitialized variable is passed to the function or procedure.I believe this would be a nice feature. It would make programs that use it more self documenting and, it would also probably make future automatic translation of MS headers a bit simpler and more likely to be correct.I see no reason to add something like this. It complicates the language and adds a new keyword with no real gain.
There is another reason too: currently the -gt compiler switch incorrectly assumes that an out parameter is not initialized by the caller. out is very clear, it tells the compiler that the variable will be written to in the function/procedure, it says absolutely nothing about the initialization state of the variable being passed to the function/procedure.Do you have an example for that? Cause it's a bit unclear what exactly you mean here...
inout would provide a way for the compiler to help the programmer write better code and, it would also justify - the currently incorrect - assumption made by the -gt switch.
This is done by var already. There is no reason to add a new keyword for something that already exists.No. It is not done by var already.
There is another reason too: currently the -gt compiler switch incorrectly assumes that an out parameter is not initialized by the caller. out is very clear, it tells the compiler that the variable will be written to in the function/procedure, it says absolutely nothing about the initialization state of the variable being passed to the function/procedure.Do you have an example for that? Cause it's a bit unclear what exactly you mean here...
inout would provide a way for the compiler to help the programmer write better code and, it would also justify - the currently incorrect - assumption made by the -gt switch.
Even if that is true (which is only so for older code), this can be handled with local switches so that if you use a VAR parameter under that define, the procedure signature gets the correct meaning of VAR for errorhandling.I'm not seeing clearly what you mean there. Can you give an example ?
I don't see ANY reason to make this yet another DIY incompatible syntax.What would inout it be incompatible with ? or are you thinking about something else ?
Even if that is true (which is only so for older code), this can be handled with local switches so that if you use a VAR parameter under that define, the procedure signature gets the correct meaning of VAR for errorhandling.I'm not seeing clearly what you mean there. Can you give an example ?
{$someswitchVAR VARISINOUT}
procedure xx (var yy:zz); // this signature gets mandatory in and output attributes for the static analyser.
I don't see ANY reason to make this yet another DIY incompatible syntax.What would inout it be incompatible with ? or are you thinking about something else ?
are you suggesting changing the semantics of the var keyword by using a switch to turn into inout ? A var is mandatory but, it doesn't tell the compiler anything about whether or not the variable should be initialized before passing it. Adding semantics to "var" could definitely cause a lot of incompatibilities. "var" should be left alone.Code: [Select]{$someswitchVAR VARISINOUT}
procedure xx (var yy:zz); // this signature gets mandatory in and output attributes for the static analyser.
I don't see ANY reason to make this yet another DIY incompatible syntax.Don't include it in $mode Delphi. It certainly wouldn't be the first time FPC has a feature that Delphi doesn't and, here is the point: inout is simply a mechanism for the programmer to inform the compiler that a variable should have been initialized before passing it as a parameter and that the variable's value will be changed in the called function/procedure. Given that information the compiler can let the programmer know that he/she may have failed to initialize the variable before passing it (which neither var nor out are sufficient to determine that omission) and warn the programmer if he/she may have failed to set a value in the function/procedure (which var cannot do but out can - which is the whole reason to have added "out" to the language, it's its reason to exist.) "inout" simply completes the set of possibilities. I presume you can see the point now.What would inout it be incompatible with ? or are you thinking about something else ?
Delphi, $mode delphi, but more importantly I don't see the point and a language addition is an important thing.
[…] 3. inout […]And I'd like to have the modifier
are you suggesting changing the semantics of the var keyword by using a switch to turn into inout ? A var is mandatory but, it doesn't tell the compiler anything about whether or not the variable should be initialized before passing it.Code: [Select]{$someswitchVAR VARISINOUT}
procedure xx (var yy:zz); // this signature gets mandatory in and output attributes for the static analyser.
noInNoOut
inout would make it clear to the compiler that the variable being passed _must_ be initialized before passing it as a parameter. This would enable the compiler to emit a hint/warning if the variable has not been initialized.But it already works with var:
"VAR" is a token for read/write. If for some reason you want to change semantics for warnings for some minor cases, that is the way to go.var is to tell the compiler that the variable should be passed by reference. Nothing else. At most, it could be construed to mean that the variable will be written to, which would actually not be correct, since passing by reference is often done for performance reasons (and also to prevent stack overflows), not to tell the compiler that the variable will be modified.
But it already works with var:You are right, it does but, it really shouldn't. There is no implication in the keyword "var" that a variable should have been initialized (it often isn't and that is not an error.) It really shouldn't generate a hint for that case and, generating it only contributes to drown really important hints in a large number of hints that are of little to no value.project1.lpr(9,9) Hint: Variable "Y" does not seem to be initialized
procedure Test(var X: Integer); begin X := 1; end; var Y: Integer; begin Test(Y); end.
var is to tell the compiler that the variable should be passed by reference.Isn't that the complete set of possibilities?
out does exactly the same thing as var, that is, pass by reference but, in addition to that, it lets the compiler know that the variable will be written to,[...]
constref is yet another case of something that does exactly the same thing as var, which is - again - pass by reference but,
Isn't that the complete set of possibilities?No, because "var" does not imply "in" (in other words, it doesn't mean the variable is initialized) nor does it imply "out" (it may just be read). var implies nothing. The compiler cannot (and in the case of FPC, should not) make any assumptions as to how a "var" will be used. In some cases, it will only be read, in other cases, only written to and in yet others cases, read and written. All of those are a correct use of a "var".
constref = in
out = out
var = inout
@Marco"VAR" is a token for read/write. If for some reason you want to change semantics for warnings for some minor cases, that is the way to go.var is to tell the compiler that the variable should be passed by reference.
I came to that idea when reading a Pascal standards report written by "some guy" who goes by the name of Niklaus Wirth. On page 72 of his report he writes:@Marco"VAR" is a token for read/write. If for some reason you want to change semantics for warnings for some minor cases, that is the way to go.var is to tell the compiler that the variable should be passed by reference.
However did you come by that idea? , it is read/write calling convention semantics.
In program 11.2 none of the values in array g are altered; i.e.That seems to be clear. var may be used just for performance reasons and avoid potential memory problems. IOW, there is no implication whatsoever as to what the use of a var is going to be. The only thing it tells the compiler is that the variable will be passed by reference and absolutely nothing about whether the variable is only read, only written or read and written.
g is not a result. Consequently g could have been defined as a
value parameter without affecting the end result. To understand
why this was not done. it is helpful to look at the
implementation.
A procedure call allocates a new area for each value parameter;
this represents the local variable. The current value of the
actual parameter is "copied" into this location; exit from the
procedure simply releases this storage.
If a parameter is not used to transfer a result of the
procedure, a value parameter is generally preferred. The
referencing is then quicker, and one is protected against
mistakenly altering the data. However in the case where a
parameter is of a structured type (e.g. an array), one should be
cautious, for the copying operation is relatively expensive, and
the amount of storage needed to allocate the copy may be large.
Because referencing of each element in the array occurs only
once, it is desirable to define the parameter as a variable
parameter.
Yes, the a warnings-only directive is micromanaging. But even more so is inventing new syntax for it.To be precise (which is a necessary characteristic when writing compilers), there is no new syntax. There would be a new keyword which would syntactically take the place of "var", "out" and/or "constref" depending on how the programmer intends to use the variable.
I can't help but wonder how you allowed the "constref" and "out" "inventions".
OUT is delphi,There is nothing wrong with "out". It gives information to the compiler which in turn allows it to warn a programmer that his/her "out" parameter has not been written to. That's a good thing.
... and I was against constref back then, and still am. I also think that should have been solved with directives rather than syntax. It would have made implementing IUnknown a lot easier.is keeping track of the reference count in managed types what makes you avert to "out" and "constref" ?
You are right, it does but, it really shouldn't.Do you want to enter a new keyword "inout" to fully reproduce the current "var" behavior, but additionally want "var" to behave differently?
No, definitely not. I don't want "var" to behave any different than it does now.You are right, it does but, it really shouldn't.Do you want to enter a new keyword "inout" to fully reproduce the current "var" behavior, but additionally want "var" to behave differently?
OUT is delphi,There is nothing wrong with "out". It gives information to the compiler which in turn allows it to warn a programmer that his/her "out" parameter has not been written to. That's a good thing.
... and I was against constref back then, and still am. I also think that should have been solved with directives rather than syntax. It would have made implementing IUnknown a lot easier.is keeping track of the reference count in managed types what makes you avert to "out" and "constref" ?
Btw Out parameters are dangerous if you pass the same managed type by const and by out. e.g. x(s,s); where the first param is out, and the second const.I wouldn't go as far as saying "out" parameters are dangerous, I'd say it's important for the programmer to know precisely what the compiler does. "constref" is FPC specific but, it helps ensuring that things that should not change do not change but, you're right, being FPC specific it does causes minor inconveniences when using another Pascal compiler (in my case Delphi 2) but, in spite of that, I use it whenever applicable.
<snip>
I avoid constref because it is non-delphi.
<snip>
I don't use out much because I simply rarely feel the need to micromanage beyond VAR, and I have been bitten by the double reference bug (and some cases I didn't cared to research into detail). I suspect it is as much that it can make it harder to debug (more implicit code).
I wouldn't go as far as saying "out" parameters are dangerous, I'd say it's important for the programmer to know precisely what the compiler does.
"constref" is FPC specific but, it helps ensuring that things that should not change do not change but, you're right, being FPC specific it does causes minor inconveniences when using another Pascal compiler (in my case Delphi 2) but, in spite of that, I use it whenever applicable.
I'm a strong believer in a programmer giving as much information as possible to the compiler, that way the compiler can work for the programmer and verify that what the programmer is doing is consistent with the information the compiler has been given.
It helps overcome the characteristic that making mistakes is human. It also often helps catching small but, important design mistakes early in the development cycle instead of catching them during system testing when making changes is usually much more laborious and prone to introduce incompatibilities with other modules.
The risks for mistakes with later modifications also increases if you don't grasp all consequences immediately. IOW the KISS principle applies.That reminds me what a smart guy said (his name was Einstein) "make things as simple as possible but no simpler". I think he had point. :)
All I would like to see is an "inout" keyword, that is "variation" of the "var" keyword that let's the compiler know that the variable should be initialized before being passed as a parameter and that the variable should be written to in the function/procedure. That way the compiler can emit a warning to the programmer if the variable isn't used according to the way it's declared.The compiler already knows if the variable is initialized and gives a hint. Do you want it to issue a warning for that with new syntax?
The risks for mistakes with later modifications also increases if you don't grasp all consequences immediately. IOW the KISS principle applies.That reminds me what a smart guy said (his name was Einstein) "make things as simple as possible but no simpler". I think he had point. :)
The compiler already knows if the variable is initialized and gives a hint. Do you want it to issue a warning for that with new syntax?No. The problem is that there the compiler is emitting a hint for a non-initialized "var" that it really shouldn't be emitting. Here are the cases:
A bit of calling convention and warning management is good. Obsessing about it a poison.It really is a terrible thing to want things done correctly. It's so much easier to have them all messed up.
1. for a var, the compiler cannot make any assumptions as to whether the variable is initialized or not, any assumption in that regard is simply incorrect and should be fixed. FPC is emitting a hint for an un-initialized variable. It shouldn't be doing that since passing an uninitialized var is correct and very common.I do not think so. In my opinion, if a variable is declared as "var", then the function can read its value, which means that it is incorrect to pass an uninitialized variable to the function. Another thing is that there are a lot of incorrectly declared functions that just migrated from the time when there was no "out" modifier. As I understand it, introducing "inout" does not solve this problem, so this argument I reject. Because if we enter "inout", in any case we will need to rewrite many functions to "inout" and replace the meaning of "var" with "out". In my opinion, it is more correct to rewrite many functions from "var" to "out" without changing the meaning of "var" and introducing new syntax.
I do not think so. In my opinion, if a variable is declared as "var", then the function can read its value, which means that it is incorrect to pass an uninitialized variable to the function.No, that is incorrect. The passage from Niklaus Wirth's Pascal report makes it very clear. No assumptions can be made nor are applicable to the initial state of a "var" because passing by reference is often done for performance reasons and/or to avoid potential stack overflows.
Another thing is that there are a lot of incorrectly declared functions that just migrated from the time when there was no "out" modifier. As I understand it, introducing "inout" does not solve this problem, so this argument I reject. Because if we enter "inout", in any case we will need to rewrite many functions to "inout" and replace the meaning of "var" with "out". In my opinion, it is more correct to rewrite many functions from "var" to "out" without changing the meaning of "var" and introducing new syntax.I'm glad you brought that up. If FPC was giving the _correct_ interpretation to "var" then it wouldn't be generating all those useless hints.
"var" is limited to inform the compiler that a variable should be passed by reference. Nothing else. That's its definition in the Pascal language. There is nothing else associated with "var".We say the same about "value parameters". These are only "value parameters" and nothing more. "Value parameters are passed by value, while variable parameters are passed by reference", but otherwise they are the same. Parameters may contain garbage, but the compiler must be silent.
We say the same about "value parameters". These are only "value parameters" and nothing more. "Value parameters are passed by value, while variable parameters are passed by reference", but otherwise they are the same. Parameters may contain garbage, but the compiler must be silent.No, that is logically incorrect.
A bit of calling convention and warning management is good. Obsessing about it a poison.It really is a terrible thing to want things done correctly. It's so much easier to have them all messed up.
No, but *correctly* and *messed up* are horribly subjective.What a horrible thing to say, for a mathematician they aren't.
A value parameter should be read otherwise there is no reason to pass it as a parameter.A var parameter should be read otherwise there is no reason to pass it as var not out.
[/quote]No, but *correctly* and *messed up* are horribly subjective.What a horrible thing to say, for a mathematician they aren't.
One thing is clear, that feature will not make it into FPC. Logical consistency and correctness are obviously not priorities and, following standards is done when convenient. Standards are just "ideas" anyway.
A var parameter should be read otherwise there is no reason to pass it as var not out.Not true. A var parameter isn't meant to state that a parameter will be read or written, only that it is passed by reference.
Not true. A var parameter isn't meant to state that a parameter will be read or written, only that it is passed by reference.Binary logic. It will either be read, then there is no point "inout", or it will not, then you need to use "out". And how the parameter is passed - by reference passed or by value is no longer important.
I think a more general solution to this problem would be a dummy initialization:What is it good for? (Absolutely nothing...)
Pascal should have a specialized intrinsic variable eg "void" that is assignement compatible to anything and that represents nothing.
a := void; //This doesnt generate code, because void doesnt exist, it is a dummy
Binary logic. It will either be read, then there is no point "inout", or it will not, then you need to use "out". And how the parameter is passed - by reference passed or by value is no longer important.Serge, the point is that whether or not the language supports "out", that doesn't change the definition of "var". That's the mistake, implicitly (or explicitly) changing the definition of a language construct because of the existence of another. That is conceptually incorrect.