There's PascalABC.NET too. I liked it more from Object Free Pascal, not because it can use the full power of .NET but because I found their Pascal Dialect to be more modern and freedom than yours (just my own opinion). For example, I could declare varible everywhere on the procedure's body, don't have to declare it all on var:Free Pascal is rather "purist" and your request is I believe has been discussed previously and rejected. Decision regarding importing language features need to be taken carefully because once done, it's a responsibility to maintain. You can take a look at various ideas ever proposed here (http://wiki.lazarus.freepascal.org/Modernised_Pascal), in which some of them have been implemented. In case you don't know, DelphiWebScript dialect in SmartPascal also implements that inline declaration feature, among others.
There's PascalABC.NET too. I liked it more from Object Free Pascal, not because it can use the full power of .NET but because I found their Pascal Dialect to be more modern and freedom than yours (just my own opinion).
There's PascalABC.NET too. I liked it more from Object Free Pascal, not because it can use the full power of .NET but because I found their Pascal Dialect to be more modern and freedom than yours (just my own opinion).
(I still fail to see what "modern" has to do with imitating 1970s C syntax. The two years that Pascal is older than C can't matter that much?)
Because all other languages support thisWell the former is not quite true: they are either C derived languages or are scripting languages. And as I demonstrated, in pascal like languages, the "feature" is not well thought out.
@Thaddy: Thanks. FreePascal is really strict :)
Because all other languages support this (declare variables everywhere in function body) nowaday.
Most languagesI would rephrase that to "Some popular languages"... Most languages have to my knowledge a differing syntax from curly brackets.
Most languagesI would rephrase that to "Some popular languages"...
Because all other languages support this (declare variables everywhere in function body) nowaday.
for var i:=2 to round(sqrt(n)) do
Javascript, java, C#, C, C++, that is half the top 10 of the tiobe index.And only because Kernighan and Richie were too lazy to type begin/end and preferred forth order for parameters... :D :D :D ..... (true!)
Thr inline var should not be there to be like C, but to improve readability and prevent bugs caused by uninitialized variable.To a compiler engineer that makes no sense: E.G. The for part makes the implied variable always initialized and not only through type inference ...By default....Silly you... Did you really understand this....?
After a for loop the loop variable must not be used without being reinitialized. "for var" makes sure you do not accidentally use the variable. Using a loop variable after a loop must be a compile error. It makes no sense that fpc compiles code that accesses a variable it knows to be invalid
And other inplace "var .. := .." make sure the variable is initialized at its declaration. No one needs a variable that is uninitialized.
Thr inline var should not be there to be like C, but to improve readability and prevent bugs caused by uninitialized variable.Sorry but that is wrong: https://www.freepascal.org/docs-html/ref/refsu58.html
After a for loop the loop variable must not be used without being reinitialized.
If the loop was terminated prematurely with an exception or a break statement, the loop variable retains the value it had when the loop was exited.
Besides this, and while I am strictly against it, but for the case that such a limited scope variable should be desired:For all intend and purpose, I completely agree with you,
1) if all loops where to be restricted, then the "var" keyword would not be needed
2) in any case, since this is pascal and therefore types are required, it would have to be: for i:integer = 0 to 5 // it could be byte, or anything.
So there a cases where the loop variable can be accessed after the loop.That's only for morons. The state is undetermined. Although the frivolous rely on it this has never been the case.
So there a cases where the loop variable can be accessed after the loop.Indeed, since introduction of Break and Exit (and any other early exit mechanism, if any). The original design perhaps considers range boundary, i.e.: in Pascal it's possible to create a for loop that iterates from Low(SomeIntegerType) to High(SomeIntegerType), that doesn't have while loop counterpart because that High() expression results in maximum value of the type, therefore +1 will wrap it around (or range check error if activated), hence the idea of making it undefined after the loop instead to avoid people reusing the unexpected value.
There's PascalABC.NET too. I liked it more from Object Free Pascal, not because it can use the full power of .NET but because I found their Pascal Dialect to be more modern and freedom than yours (just my own opinion).
(I still fail to see what "modern" has to do with imitating 1970s C syntax. The two years that Pascal is older than C can't matter that much?)
Thr inline var should not be there to be like C, but to improve readability and prevent bugs caused by uninitialized variable.To a compiler engineer that makes no sense: E.G. The for part makes the implied variable always initialized and not only through type inference ...By default....Silly you... Did you really understand this....?
After a for loop the loop variable must not be used without being reinitialized. "for var" makes sure you do not accidentally use the variable. Using a loop variable after a loop must be a compile error. It makes no sense that fpc compiles code that accesses a variable it knows to be invalid
And other inplace "var .. := .." make sure the variable is initialized at its declaration. No one needs a variable that is uninitialized.
Usually you know your theory a bit better.... <Sigh, everybody wants to be a programmer <grumpy, can't help it, >:D >:D > >
That's a sheer lack of understanding how compilers work (not just Pascal compilers, any compiler!)
If you want this kind of variables (just loop invariants) these CAN be determined by the compiler based on the language and still be LL(1).
If it is a good choice, I doubt it, because of such ill informed comments.. (and you are not a troll, I know, it is also YOUR job to educate some people on this forum that have DWIM opinions.... :D :D ;D ;D O:-)).
Thaddy, as additional feature this would be ok.Because range parsing is already there and my suggestion is therefor possibly easier to implement because of that, doesn't need/hardly needs a new syntactical element, just re-interpretation of two already present elements.
If you don't have a variable, why bother with bounds?
"for 9 do.." or "for 9-4 do.."
But of course without iteration variable such a loop is useless in many cases. That by the way also limits the usecases of "for..in" loops imo drastically.
QuoteIf the loop was terminated prematurely with an exception or a break statement, the loop variable retains the value it had when the loop was exited.
So there a cases where the loop variable can be accessed after the loop.
After a for loop the loop variable must not be used without being reinitialized.Sorry but that is wrong: https://www.freepascal.org/docs-html/ref/refsu58.htmlQuote from: fpc-docIf the loop was terminated prematurely with an exception or a break statement, the loop variable retains the value it had when the loop was exited.
So there a cases where the loop variable can be accessed after the loop.
Using this "feature" in real code is an ugly hack. Yes, ugly hacks are allowed in Pascal too.
Maybe I misunderstood, but Delphi and FPC output 9 at the end.Run the same in Delphi.... where 9 becomes 10....
var i:integer; begin for i := 0 to 9 do writeln(i); writeln(i); for i := 0 to 9 do begin writeln(i); if i = 9 then break; end; writeln(i); end.
Maybe I misunderstood, but Delphi and FPC output 9 at the end.The point I was trying to make is exactly what you describe: whatever happens do nit rely on the value, although when you use break or exit the variable seems preserved.
If the loop was terminated prematurely with an exception or a break statement, the loop variable retains the value it had when the loop was exited.
The value of the loop variable is undefined after a loop has completed
I think - if you agree - we should ask Michael to remove the last part of the quote from the documentation, because the behavior is deterministic (by accident) and not based on the language at all.Which part? I think that the documentation is correct.
BTW the reason that the value is preserved in case of premature exit us that in that case the number of iterations may have value. But IMHO that value should be assigned to another variable on exit.
After first cycle, the correct <i> value is 9.I think you're just confused. The value is defined only if the cycle is interrupted. If it passed completely, its value is undefined. This is reflected correctly in the documentation. Delphi and FPC behaviors are consistent with the documentation.
So, if under Delphi the <i> value is 10, then Delphi works badly (but I want to see it).QuoteThe value of the loop variable is undefined after a loop has completedThis is mean, after the cycle, u can rewrite <i> value, so this can different from cycle exit value, and nothing more ore less.
I think you're just confused. The value is defined only if the cycle is interrupted. If it passed completely, its value is undefined. This is reflected correctly in the documentation. Delphi and FPC behaviors are consistent with the documentation.Yes, they are.
Show me any code, after the cycle finished, the cycle variable isn't equal to cycle exists value. So, mr. confused? :)This is only the specifics of the current implementation, which can change at any time.
Show me any code, after the cycle finished, the cycle variable isn't equal to cycle exists value. So, mr. confused? :)
...Imagine a very long function/procedure, everytime I want to use an additional temp variable I have to jump to the var section and declare it.Due to the rigor and clarity of the program is easy to read and understand. If you write a procedure that does not fit on one screen, and even more so offer to scatter in it the definition of variables, even you do not understand after half year, what's what, and even more so the other person.
Imagine a very long function/procedure, everytime I want to use an additional temp variable I have to jump to the var section and declare it.
Imagine a very long function/procedure, everytime I want to use an additional temp variable I have to jump to the var section and declare it.
This is an IDE feature. Delphi has this as ctrl-shift-V "declare variable".
Many shorthands syntax can be better solved in IDEs/editors, something that was not available in C's years of yonder.
But seriously, take javascript. The results of being able to declare your var wherever you want became so complex (
http://www.adequatelygood.com/JavaScript-Scoping-and-Hoisting.html ), that they needed a linter https://eslint.org/docs/rules/vars-on-top
It's difficult for a non-pro like me to foreknow everything to declare on var section first. Imagine a very long function/procedure, everytime I want to use an additional temp variable I have to jump to the var section and declare it.
This is not by accident, but on purpose in both Delphi and FPC and stems back from TP times.Maybe I misunderstood, but Delphi and FPC output 9 at the end.The point I was trying to make is exactly what you describe: whatever happens do nit rely on the value, although when you use break or exit the variable seems preserved.
In both dialects! - it is also documented for FreePascal - the value is undefined. Except - for some reason - when you break out of the loop. For FPC that is somewhat documented.
I think that part of the documentation should be removed. If you need the value, re-assign to another variable at the point from inside the loop that you want to break out of.
The 9-10 issue demonstrates exactly that.... the "if i = 9 then break;" tries to give an example to test against both Delphi and FPC behavior.
I think - if you agree - we should ask Michael to remove the last part of the quote from the documentation, because the behavior is deterministic (by accident) and not based on the language at all.
After the for statement terminates (provided this was not forced by a Break or an Exit procedure), the value of counter is undefined.
After a for-statement is executed, other than being left by a goto-statement, the control-variable shall be undefined.
[]After a for-statement is executed, other than being left by a goto-statement, the control-variable shall be undefined.FPC was recently even fixed to handle this correctly when loop unrolling is enabled (namely by not unrolling them in such cases).
@mercurhyono
You are user piGrimm, aren't you?
Imagine a very long function/procedure, everytime I want to use an additional temp variable I have to jump to the var section and declare it.
Well the premature exits are not in all cases goto and certainly not statements (goto is), but thanks for the explanation.[]After a for-statement is executed, other than being left by a goto-statement, the control-variable shall be undefined.FPC was recently even fixed to handle this correctly when loop unrolling is enabled (namely by not unrolling them in such cases).
Something I saw in my C days could be nice..
For COUNTER:Integer := 1 to Whatever do....
That's not exactly like in C but it makes sure the COUNTER variable never exists out side
the control loop.
I am pretty sure FPC does not support that, yet ;)
neither does it support:
if condition then begin a:= 1; DoSomethingWith(a); end; // a may be undefined... And yet you can access it
I don't think that is what @Martin_fr was referring to.echo echo echo... :D
he is making the statement that declaring "A" variable on the fly and keeping it in the loop scope only
isn't supported.
But I still like the idea of the for loop declaring the variable within the loop control setup, not inside the
loop block.
I Think it was MS C that allowed me to do that for a "FOR" control and made it go out of scope when you
left the loop block, just a temp variable.
For name:Type := StartValue to EndValue Do... or begin.. ,end;
etc
In this context you really don't even need a variable declared in the normal section, the compiler can simply
create a background variable for you and with no TYPE specified it would generate a integer;
As for allowing this behavior anywhere else I don't agree with how C or others do this, just create variables on the fly
in the code base is unorganized and leads to hard to read code.
As for allowing this behavior anywhere else I don't agree with how C or others do this, just create variables on the flyecho echo echo... :D
in the code base is unorganized and leads to hard to read code.
introducing improvements does not mean "force to use, knife under neck" afaik I can still program in pure pascal, I mean TP like; all improvements after Object down
So, introducing new concepts would not bother oldies stuck around 1870 years' rules, as long as their old fashioned sources still work the right way with no change. Ever heard about "backward compatibility"?
Doesn't really answer my question: why "for" but not "if"?
That of course is, assuming we agreed above that it was for "for" only, and not for "if".
As for your statement, which is a repeats:
No, it is "force to use". Because it will appear in public components that will have to be used. Or worse, it will appear in the rtl. The alternative is, that it will reduce the available libraries, it will make important security update unusable, ....
Variables declared ahead of the procedure (or the breakage of this) is not a feature. It is changing the fundamental design of the language.
<sarcasm>
With your argument in mind, I could also say that a modeswitch could be added, that makes {} tokens for begin/end (and (**) can be used for comments). It would be just optional so no harm.
And "*" or "->" could be used for pointer deref...
</sarcasm>
But again, even if we do not ask: why "for" but not "if"?
The question still stands: How does it help against uninitialized variables? As I said, you have uninitialized variables in c, or javascript too.
For the for loop that problem can be fixed, by having fpc issuing a warning (you can tell fpc to treat warnings as errors, so then it really will stop the issue: -Sew )
the variable of course could be flagged as duplicateYes, what I implied before. And then each time you want to add a "regular" var (in the var section), then you have to search all the code in the procedure, if maybe it is used in a loop.
make code a little more reliablePlease explain?
between compiler updates
This would stop those from trying to use the value of the loop when it exitsI doubt it. They would simple use the syntax with the normal pre-declared variable that we have today.
And that is my point, if this (declaring variables anywhere) is NOT good for other control blocks (like "if" or any other), then what makes "for" so special?I think the speciality of the 'for' iterator is quite obvious. A 'for..to' loop always has exactly one iterator. The iterator variable of the loop is read/write outside the loop, but readonly within the loop. I'm sure there were some efforts involved in the compiler design to make it working that way. One could say its an abuse of a standard variable, as their properties are changed in the certain block. Of course in a if-block nothing like that happens to a variable.
If I have many 1 liner loops, I reuse the var, if some of them are "while" loops, I still reuse the var.Thats a good point. (Would still be possible with a "dual" approach).
What makes the uninitialized var after a loop so different to other uninitialized var?For me its quite strange that the variable is initialized if the loop was interrupted by break/goto but not if it was properly finished. If I want to use the feature in case that the loop was interrupted than I first have to check if the loop even was interrupted, otherwise I couldn't rely on the iteration variables value. This means flags or something is needed. But instead such efforts I could just copy the iteration variable inside the loop, so that feature seems useless...
Well, point to you, good answer.And that is my point, if this (declaring variables anywhere) is NOT good for other control blocks (like "if" or any other), then what makes "for" so special?I think the speciality of the 'for' iterator is quite obvious. A 'for..to' loop always has exactly one iterator. The iterator variable of the loop is read/write outside the loop, but readonly within the loop.
But still, the iterator variable needs a space in memory. This has a certain size and location. The iterator could be defined as local or global variable. There may be reasons for both, especially in embedded programming. So a declaration is required and the var section is the correct place for that.At the moment "for" iterators must be local variables. (probably due to the same implementation detail)
Still, a self-declared iterator variable could be allowed.IMHO, no.
This would be an introduction of self decleration, a simple typo could change the type of the iteration variable if a explicit declared variable was intended. I see that this is not part of the pascal philosophy...You argue my case. Thanks.
This is an argument why the "break" behaviour is not a good idea (though exceptions, and an "except" block would work).Quote from: Martin_frWhat makes the uninitialized var after a loop so different to other uninitialized var?For me its quite strange that the variable is initialized if the loop was interrupted by break/goto but not if it was properly finished. If I want to use the feature in case that the loop was interrupted than I first have to check if the loop even was interrupted, otherwise I couldn't rely on the iteration variables value. This means flags or something is needed. But instead such efforts I could just copy the iteration variable inside the loop, so that feature seems useless...
So again: What makes the uninitialized var after a loop so different to other uninitialized var?
Good point. (actually 2 good points)
So again: What makes the uninitialized var after a loop so different to other uninitialized var?
It is the only case where an assignment makes the variable uninitialized
If you write i := something anywhere, the variable becomes initialized. But when you write for i := 1 to 3, it is later uninitialized. It is like a weirdly overloaded := operator
for i := 1 to 3, it is later uninitialized. It is like a weirdly overloaded := operatorYou are absolutely right. There is something very weird about the := here.
Ok let it be "as it is", no problem to me it works for 35 years.Using "[…]" is just as much hell for the parser as "<…>" already is as the former conflicts with the array syntax while the latter conflicts with comparisons. Also considering that the "[…]" syntax in const/var sections means sets (which are unordered) a more correct choice would be "(…)" which is for ordered elements in those sections and the type parameters are ordered.
about generic class<curlymathsyms> I will never use that (I can't see a knife under my neck forcing me to use improvements I do not want, as I mentioned) unless I find a way to patch the compiler, replacing "<>" with "[ ]" that is more pascalish to my taste
You take a different conclusion of my argument than me. What I mean is: Because the iterator variable is that special, directly tied to the loop and in almost all cases of local integer type. Because of this it feels a waste of time to do a declaration (of something obvious). So the aim is to make things less complicated (by omitting the decleration) and not to make them more complicated by additionally forced flags like "iterator".I think the speciality of the 'for' iterator is quite obvious. A 'for..to' loop always has exactly one iterator. The iterator variable of the loop is read/write outside the loop, but readonly within the loop.This is probably out of the need of an implementation detail, which allows the compiler to optimize the loop behaviour, but nevertheless.
[...]
That is the "for" loop can NOT declare a new variable
This would for example allow to prevent the following:Thats a crazy hack. But I apreciate the example of how easy it is to "actually break existing language features".
[...] we can modify i here, which can cause all kind of undesired effects
Yes I know it is optional, but if there are cases where it can not be used at all (not even optional), then that means that even if you want the feature you are left with some code that even you must write in the old way, and even you still will not get the "protection" you seek.I don't seek any protection, but simplycity :) The arguments about the uninitialised variable in my point of view is not about that protection after the loop is needed, but that the other way round there is no reason why the loop variable after the loop still should be accessible at all.
So the new feature would be incomplete.
To be honest, if I had the power I wouldn't want to have to decide it. There are pros and cons. Both imo strong ones.QuoteThis would be an introduction of self decleration, a simple typo could change the type of the iteration variable if a explicit declared variable was intended. I see that this is not part of the pascal philosophy...You argue my case. Thanks.
- Why do we want special/extra protection, if that uninitialized var was a "for" iterator before?In contrast to the documentation the practice shows the bahaviour that the variable is initialized to the last loop's value (At least in cases). Also this is a common feature of many programming languages.
- IMHO, *ALL* uninitialized deserve the same lever of attention/protection.
- An application certainly will be same as buggy if it hits an uninitialized var never mind if this was a "for" iterator, or otherwise uninitialized.
So again: What makes the uninitialized var after a loop so different to other uninitialized var?
What is actually assigned to "i", and when?I read it like that (for i:= 1 to 3): "loopwise assign values for i starting with 1 ending with 3", i.e.:
- This := can not be, because the right hand site does not provide a single value of the type. (even "1 to 1" is a range)
- So this := promises us that "i" will be assigned a range of its base type? That can not be.
At the moment "for" iterators must be local variables. (probably due to the same implementation detail)I tested and its possible to use a Integer declared in an other unit (making it global). I'm not sure though if the loop is actually using that address or kept locally, or is even optimized to registers.
You take a different conclusion of my argument than me. What I mean is: Because the iterator variable is that special, directly tied to the loop and in almost all cases of local integer type. Because of this it feels a waste of time to do a declaration (of something obvious). So the aim is to make things less complicated (by omitting the decleration) and not to make them more complicated by additionally forced flags like "iterator".I think the speciality of the 'for' iterator is quite obvious. A 'for..to' loop always has exactly one iterator. The iterator variable of the loop is read/write outside the loop, but readonly within the loop.This is probably out of the need of an implementation detail, which allows the compiler to optimize the loop behaviour, but nevertheless.
[...]
That is the "for" loop can NOT declare a new variable
And thats the answer to the "why": To reduce efforts. Avoid that the programmers has to consider things that the compiler can do itself.
To reduce efforts.If you do not want to give it much attention, how much effort is it to press Ctrl-Shift-C (you can even assign it to something easier)?
Equally I could say there is no reason why it should not be available (Especially after you wrote, you don't seek protection from accidentally accessing it).QuoteYes I know it is optional, but if there are cases where it can not be used at all (not even optional), then that means that even if you want the feature you are left with some code that even you must write in the old way, and even you still will not get the "protection" you seek.I don't seek any protection, but simplycity :) The arguments about the uninitialised variable in my point of view is not about that protection after the loop is needed, but that the other way round there is no reason why the loop variable after the loop still should be accessible at all.
So the new feature would be incomplete.
To be honest, if I had the power I wouldn't want to have to decide it. There are pros and cons. Both imo strong ones.
Quote- Why do we want special/extra protection, if that uninitialized var was a "for" iterator before?In contrast to the documentation the practice shows the bahaviour that the variable is initialized to the last loop's value (At least in cases). Also this is a common feature of many programming languages.
- IMHO, *ALL* uninitialized deserve the same lever of attention/protection.
- An application certainly will be same as buggy if it hits an uninitialized var never mind if this was a "for" iterator, or otherwise uninitialized.
So again: What makes the uninitialized var after a loop so different to other uninitialized var?
BUT: I wouldn't add protection because of that. Rather I'd make it a documented feature.Ok, so that would be a different new feature.
Well we all got used to read it like this.What is actually assigned to "i", and when?I read it like that (for i:= 1 to 3): "loopwise assign values for i starting with 1 ending with 3", i.e.:
But it is about "saving to type a few extra chars". Is that correct?No, its not about typing a few extra chars. Its about taking an additional step/action. When one is very common to a programming language than this doesn't matter as its automated in mind (or by IDE-help). The same holds for begin..end. I like "end" but I don't like "begin". The few more characters don't matter at all. But I don't 'feel' the block of a if-condition or for-loop. For me "for i:=1 to 5 do begin" is the head of the loop, "end;" is the tail of the loop. In this way of thinking the "begin" keyword is absolutely useless. I would say its only there to allow single statement loops. Again, for someone with experience in a language this gets automized and doesn't matter at all. By now I feel nearly indifferent to it. When starting with Freepascal it was quite annoying though. The importance of such features is not easy to grap, to quantify or whatever, as its not hard objective facts. But all programmers are humans having emotions and liking or not liking a language is part of the game. (In general - obviously - I really like Freepascal).
"foo.count" may change from integer to cardinal, after I wrote the loop.I don't exactly understand. If the compiler always choses an Integer type for undeclared loop variables and foo.count changes to cardinal, then its the same situation as I would have declared the integer manually (because I also choose Integer as standard).
If there even is as much as the possibility that I have somewhere a loop that uses the derived type for the iterator, rather than a declared type, then I will have to search my entire code base
[...]
And finally, I prefer it that if foo.count changes to an incompatible type, then the compiler will not compile the loop.
Actually, I have plenty of loops that iterate over other enum types. (Search the IDE for "procedure dbgs" / typical pattern: for i := low(enumtype) to high(...)...)Yes, my view point may be limited, I very rarely use enumerators.
But even if it was mostly integer. The declaration of any variable on top, tells me more than the type it has. It tells me the name is used as an identifier.Is this a real issue? My loops mostly have standard names and I wouldn't use a loop variable as a temporary integer just because its lying around.
As I wrote before in this thread, if the loop iterator would not be declared in the var block, and I wanted to add a variable (for none loop purpose), then I would have to search the entire procedure body for any "for" loops, so I know the name is not used. That is a massive amount of extra work.
Agreed. It's like always, considering all circumstances makes a small change quite troublesome if it is done right.QuoteBUT: I wouldn't add protection because of that. Rather I'd make it a documented feature.Ok, so that would be a different new feature.
If it where to be implemented, no objections from me.
But I would severely hope the optimizer in fpc would be enhanced for enough to detect
It may be different in c/js, but why would I even think about rules of a language that is not the one I currently write code in?There's always space for improvement. For many features its clear that they use a different philosophy, but not for all.
From my side we don't need to dig any deeper into that topic. I'm already convinced that there are some pitfalls. Perhaps thats such kind of feature where only actual usage could clarify the benefits and costs. Of course thats not easily possible.
<cynism>
<sarcasm>
Next topic: Should shell script support object orientation?
</sarcasm>
No, its not about typing a few extra chars. Its about taking an additional step/action. When one is very common to a programming language than this doesn't matter as its automated in mind (or by IDE-help). The same holds for begin..end. I like "end" but I don't like "begin".You seem to forget that the curly brackets mob have the same issue and for the same reason: "{" is short for "begin", "}" is short for "end" nothing less, nothing more.
"{" is short for "begin", "}" is short for "end" nothing less, nothing more.Yes, begin..end is nearly as bad as {}. The modula-2 syntax is much better.
So now it is NOT about the uninitialized behaviour of the iterator after the loop. But it is about "saving to type a few extra chars". Is that correct?
As I wrote before in this thread, if the loop iterator would not be declared in the var block, and I wanted to add a variable (for none loop purpose), then I would have to search the entire procedure body for any "for" loops, so I know the name is not used. That is a massive amount of extra work.
So in order to know about all the identifier names that are already used in the procedure, the iterator too must be listed in the var block. (never mind in which way, but it must be there)
Further morefoo.count may be cardinal. Mixed signed expression may give a 64 bit result. But I most likely do not want "i" to be int64. So I do need to specify it.
for i := 0 to foo.count -1
Or I may want I to be a smaller type, because it will never exceed it, and a lot of operations in the loop depend on it.
Of course, I understand, if I need a type different from the declared type, then I can still set it. But that is not all of it. "foo.count" may change from integer to cardinal, after I wrote the loop.
If there even is as much as the possibility that I have somewhere a loop that uses the derived type for the iterator, rather than a declared type, then I will have to search my entire code base (and that really is a lot of work, especially if the change is in a package on which many projects depend).[/u]
And finally (and on that your opinion may differ), I prefer it that if foo.count changes to an incompatible type, then the compiler will not compile the loop.
So I can check it, if changing the declared type will work as I expect it, or if it will have side effects. (assuming the loop body compiles with the new iterator type, otherwise the derived iterator will give an error too)
var i: integer;
n: cardinal;
begin
n := MaxInt + 2;
writeln(n);
for i := 0 to n - 1 do begin
writeln(i);
end;
end.
var i: cardinal;
n: cardinal;
begin
n := 0;
writeln(n);
for i := 0 to n - 1 do begin
writeln(i);
end;
end.
var b: byte;
begin
b := 100;
writeln(b * b);
end.
The "var i" is not within the "begin/end" scope. So why would I assume it to be limited to that scope. I would of course assume, that it will be scoped to the end of the procedure (or maybe enclosing begin/end, if there was another).
Same as I would do in this case:
if a= b then begin foo(); var c: integer; // statement declaring c, ends at the ";" if bar() then begin c:= 1; end; c := 2; end; // scope for c ends here
It may be different in c/js, but why would I even think about rules of a language that is not the one I currently write code in?
function a;
function b;
var i: integer;
begin
//i in scope
end;
begin
//i not in scope
end;
This is freedom:
:D
plus the fact there are problems on containers limits
assuming you dont want to call "pack" each iterationI just today showed you why that is not the case in another thread.
This compiles and never runs the loop:Code: [Select]var i: integer;
n: cardinal;
begin
n := MaxInt + 2;
writeln(n);
for i := 0 to n - 1 do begin
writeln(i);
end;
end.
This compiles and runs the loop many many times:Code: [Select]var i: cardinal;
n: cardinal;
begin
n := 0;
writeln(n);
for i := 0 to n - 1 do begin
writeln(i);
end;
end.
Warning: range check error while evaluating constants (2147483649 must be between -2147483648 and 2147483647)
Warning: range check error while evaluating constants (-1 must be between 0 and 4294967295)
And this prints 10000. Apparently all smaller types are converted to sizeint/sizeuint when usedCode: [Select]var b: byte;
begin
b := 100;
writeln(b * b);
end.
Cocky
Ok let it be "as it is", no problem to me it works for 35 years.Using "[…]" is just as much hell for the parser as "<…>" already is as the former conflicts with the array syntax while the latter conflicts with comparisons. Also considering that the "[…]" syntax in const/var sections means sets (which are unordered) a more correct choice would be "(…)" which is for ordered elements in those sections and the type parameters are ordered.
about generic class<curlymathsyms> I will never use that (I can't see a knife under my neck forcing me to use improvements I do not want, as I mentioned) unless I find a way to patch the compiler, replacing "<>" with "[ ]" that is more pascalish to my taste
Ok let it be "as it is", no problem to me it works for 35 years.Using "[…]" is just as much hell for the parser as "<…>" already is as the former conflicts with the array syntax while the latter conflicts with comparisons. Also considering that the "[…]" syntax in const/var sections means sets (which are unordered) a more correct choice would be "(…)" which is for ordered elements in those sections and the type parameters are ordered.
about generic class<curlymathsyms> I will never use that (I can't see a knife under my neck forcing me to use improvements I do not want, as I mentioned) unless I find a way to patch the compiler, replacing "<>" with "[ ]" that is more pascalish to my taste
NOPE I will patch the compiler definitely with '[ ... ]', …
Cocky programmers should be put to rest.
Have you tried these:
Gambas
Although not fully compatible but you can think it is as a VB/VB.net for Linux.
https://en.wikipedia.org/wiki/Gambas
FreeBASIC
It is a multi platform BASIC compiler, it provides syntax compatibility with programs originally written in Microsoft QuickBASIC.
https://en.wikipedia.org/wiki/FreeBASIC
QB64
A self hosting BASIC compiler. It can be used to write simple Android app.
https://en.wikipedia.org/wiki/QB64
They all are free and look interesting.