Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-pascal / 2009-11

private integer is an illegal counter variable

14 messages · 7 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Juha Manninen

Hello,

If I define a private integer:

  TDemo = class(TCustomApplication)
  private
    i: integer;
    ...

and in a protected method I use it:

  for i := 0 to List.Count - 1 do
    ...

then I get an error:
Error: Illegal counter variable

Moving it to method's var section helps.
Method's var section is also better place for it in general, but still it should be legal to use a private member as counter var.

Bug or feature?

Regards,
Juha Manninen

Jonas Maebe
to Juha Manninen
Juha Manninen wrote 18 lines
If I define a private integer: TDemo = class(TCustomApplication) private i: integer; ... and in a protected method I use it: for i := 0 to List.Count - 1 do ... then I get an error: Error: Illegal counter variable Moving it to method's var section helps. Method's var section is also better place for it in general, but still it should be legal to use a private member as counter var.

The reason is that a for-loop tries to make a number of reasonable guarantees that the counter variable cannot be modified during the loop. E.g., direct assignments to a counter variable are forbidden inside the loop (except in TP-mode). If you use a private field, then any method of that class called in the body of the loop can easily (accidentally) change the value of the counter variable, completely messing up the loop.

Jonas

Frank Peelo
to Jonas Maebe
Jonas Maebe wrote 27 lines
On 27 Nov 2009, at 15:49, Juha Manninen wrote: > If I define a private integer: > > TDemo = class(TCustomApplication) > private > i: integer; > ... > > and in a protected method I use it: > for i := 0 to List.Count - 1 do > ... > > then I get an error: > Error: Illegal counter variable > > Moving it to method's var section helps. > Method's var section is also better place for it in general, but still it > should be legal to use a private member as counter var. The reason is that a for-loop tries to make a number of reasonable guarantees that the counter variable cannot be modified during the loop. E.g., direct assignments to a counter variable are forbidden inside the loop (except in TP-mode). If you use a private field, then any method of that class called in the body of the loop can easily (accidentally) change the value of the counter variable, completely messing up the loop.

In any case, why would one want a loop counter to have any more than the minimum possible scope? Why would one want it to be a class data member at all? Surely it would be far better/neater/more elegant, if it is used by methods, to pass it as a parameter?

FP

Juha Manninen
to Frank Peelo
Frank Peelo wrote 11 lines
> The reason is that a for-loop tries to make a number of reasonable > guarantees that the counter variable cannot be modified during the loop. > E.g., direct assignments to a counter variable are forbidden inside the > loop (except in TP-mode). If you use a private field, then any method of > that class called in the body of the loop can easily (accidentally) > change the value of the counter variable, completely messing up the loop. In any case, why would one want a loop counter to have any more than the minimum possible scope? Why would one want it to be a class data member at all? Surely it would be far better/neater/more elegant, if it is used by methods, to pass it as a parameter?

Right, it is better define it locally. I did this experiment by accident when copying code around.
This is actually a good deviation from Delphi's rules. No problem here.

There are some other deviations which look weird for me, like treating "string" as a dynamic ansistring sometimes but as an old shortstring sometimes. That is in the default {$mode objfpc}.
Fortunately there is {$mode delphi} which behaves more logically. I understand it is important to support also the old shortstring but it should be defined explicitly and "string" should always mean just one thing.

Well, I guess this has been discussed before...
I can always use mode delphi.

Juha Manninen

Jonas Maebe
to Juha Manninen
Juha Manninen wrote
I understand it is important to support also the old shortstring but it should be defined explicitly and "string" should always mean just one thing.

ansistring and shortstring always mean just one thing. "string" originally meant shortstring in Turbo Pascal, and in Delphi it means shortstring with {$h-} and ansistring with {$h+} (and {$h+} is the default in Delphi and in FPC's Delphi mode).

Jonas

Mattias Gaertner
to Juha Manninen: Right, it is better define it locally. I did this experiment by accident when copying…
Show quoted text 25 lines
On perjantai, 27. marraskuuta 2009 23:52:30 Frank Peelo wrote: > > The reason is that a for-loop tries to make a number of reasonable > > guarantees that the counter variable cannot be modified during the loop. > > E.g., direct assignments to a counter variable are forbidden inside the > > loop (except in TP-mode). If you use a private field, then any method of > > that class called in the body of the loop can easily (accidentally) > > change the value of the counter variable, completely messing up the loop. > > In any case, why would one want a loop counter to have any more than the > minimum possible scope? Why would one want it to be a class data member > at all? Surely it would be far better/neater/more elegant, if it is used > by methods, to pass it as a parameter? Right, it is better define it locally. I did this experiment by accident when copying code around. This is actually a good deviation from Delphi's rules. No problem here. There are some other deviations which look weird for me, like treating "string" as a dynamic ansistring sometimes but as an old shortstring sometimes. That is in the default {$mode objfpc}. Fortunately there is {$mode delphi} which behaves more logically. I understand it is important to support also the old shortstring but it should be defined explicitly and "string" should always mean just one thing. Well, I guess this has been discussed before...

Yes, a lot.
And there are many reasons why there are so many string types nowadays. Simply use {mode objfpc}{$h+} like lazarus suggests.

I can always use mode delphi.

Then you will loose some fpc features.

Mattias

Juha Manninen
to Jonas Maebe: ansistring and shortstring always mean just one thing. "string" originally meant…
Jonas Maebe wrote 9 lines
On 27 Nov 2009, at 23:43, Juha Manninen wrote: > I understand it is important to support also the old shortstring but it > should be defined explicitly and "string" should always mean just one > thing. ansistring and shortstring always mean just one thing. "string" originally meant shortstring in Turbo Pascal, and in Delphi it means shortstring with {$h-} and ansistring with {$h+} (and {$h+} is the default in Delphi and in FPC's Delphi mode).

So {$h+} is the important part here. Ok, I partly misunderstood the settings.

From Mattias:

Then you will loose some fpc features.

fpc mode requires more strict syntax with function pointers (event handler assignment). It doesn't sound like a big deal. What else? I must study this little more.

Juha

Jürgen Hestermann
to Mattias Gaertner: On Sat, 28 Nov 2009 00:43:39 +0200 Yes, a lot. And there are many reasons why there are…
And there are many reasons why there are so many string types nowadays.

True.

Simply use {mode objfpc}{$h+} like lazarus suggests.

I think the root cause of all these problems are generic types. They cause more trouble than they avoid. I would suggest that noone never uses such generic types but uses shortstring or ansistring (or...) as they need. Telling people to simply use this or that compiler switch is not the solution (you have to explain this over and over again). Generic types should be the exception and not the norm. It begs for trouble in many situations. Using strict types also lets the user read more about the nature of these types and therefore knows more about possible side effects. Someone who has shortstings in mind when using strings would surely use it in a different way as someone who has ansistrings in mind (provided he knows how they are handled by the compiler). And telling people clearly about the implementation of these different types is much better than obscuring them by generic types.

Flávio Etrusco
to Jürgen Hestermann
Jürgen Hestermann wrote 20 lines
> And there are many reasons why there are so many string types nowadays. True. > Simply use {mode objfpc}{$h+} like lazarus suggests. I think the root cause of all these problems are generic types. They cause more trouble than they avoid. I would suggest that noone never uses such generic types but uses shortstring or ansistring (or...) as they need. Telling people to simply use this or that compiler switch is not the solution (you have to explain this over and over again). Generic types should be the exception and not the norm. It begs for trouble in many situations. Using strict types also lets the user read more about the nature of these types and therefore knows more about possible side effects. Someone who has shortstings in mind when using strings would surely use it in a different way as someone who has ansistrings in mind (provided he knows how they are handled by the compiler). And telling people clearly about the implementation of these different types is much better than obscuring them by generic types.

Maybe FPC could have a directive to disable/undeclare the 'string' type/keyword ;-)

-Flávio

Juha Manninen
to Jürgen Hestermann: True. I think the root cause of all these problems are generic types. They cause more…
Jürgen Hestermann wrote 19 lines
> And there are many reasons why there are so many string types nowadays. True. > Simply use {mode objfpc}{$h+} like lazarus suggests. I think the root cause of all these problems are generic types. They cause more trouble than they avoid. I would suggest that noone never uses such generic types but uses shortstring or ansistring (or...) as they need. Telling people to simply use this or that compiler switch is not the solution (you have to explain this over and over again). Generic types should be the exception and not the norm. It begs for trouble in many situations. Using strict types also lets the user read more about the nature of these types and therefore knows more about possible side effects. Someone who has shortstings in mind when using strings would surely use it in a different way as someone who has ansistrings in mind (provided he knows how they are handled by the compiler). And telling people clearly about the implementation of these different types is much better than obscuring them by generic types.

A generic "string" type makes a lot sense when switching between dynamic string types (AnsiString, UnicodeString...).
Delphi managed to do the switch almost transparently because they had designed their libraries well. Old code using AnsiString just worked after compiling it for UnicodeString.
The historical ShortString is handled very differently (explicit memory management etc.). It is a different type semantically and so it should be different also syntactically.

This apparently small syntax detail has a wider symbolic message. When people here are seriously arguing about how important ShortString is ('cause you can save 3 bytes or something...) the message for potential new Pascal programmers is like:
"If you think ShortString as a default string type is important because it was invented at 1970 then welcome to our Old Farts' Freak Club. Otherwise please use some contemporary language."
I am almost an old fart by age but still I am looking for new innovations. Whole computing is still very young and is advancing rapidly. Development tools must advance, too.
Now Object Pascal has a place in this ecosystem as a compiled language with clear syntax. Virtual machines are still memory hogs and C++ is ugly. After 50 years nobody cares if virtual machines hog memory because computers will have so much resources but not yet so.

I am happy this language is evolving. Generics syntax is a good thing. Virtual machines or garbage collections would not belong here but I guess they are not even planned.

Juha Manninen

Mattias Gaertner
to Juha Manninen
Show quoted text 15 lines
[...] This apparently small syntax detail has a wider symbolic message. When people here are seriously arguing about how important ShortString is ('cause you can save 3 bytes or something...) the message for potential new Pascal programmers is like: "If you think ShortString as a default string type is important because it was invented at 1970 then welcome to our Old Farts' Freak Club. Otherwise please use some contemporary language." I am almost an old fart by age but still I am looking for new innovations. Whole computing is still very young and is advancing rapidly. Development tools must advance, too. Now Object Pascal has a place in this ecosystem as a compiled language with clear syntax. Virtual machines are still memory hogs and C++ is ugly. After 50 years nobody cares if virtual machines hog memory because computers will have so much resources but not yet so.

One of the innovations of the last years is the higher demand for multi threaded apps.
Reference counted strings need atomic operations and are therefore much slower as soon as you start another thread.
This could give shortstring a renaissance.

Mattias

Luca Olivetti
to Mattias Gaertner

En/na Mattias Gaertner ha escrit:

One of the innovations of the last years is the higher demand for multi threaded apps. Reference counted strings need atomic operations and are therefore much slower as soon as you start another thread.

I always protect multithreaded sting access with a critical section. Do you mean it is not needed?

Bye

Luca
Jonas Maebe
to Luca Olivetti
Luca Olivetti wrote
I always protect multithreaded sting access with a critical section. Do you mean it is not needed?

The reference counting of ansistrings/... is thread safe. Accessing the characters etc still requires explicit synchronisation if at least one writer is involved.

Jonas

Flávio Etrusco
to Jonas Maebe
Jonas Maebe wrote 9 lines
On 01 Dec 2009, at 18:03, Luca Olivetti wrote: > I always protect multithreaded sting access with a critical section. > Do you mean it is not needed? The reference counting of ansistrings/... is thread safe. Accessing the characters etc still requires explicit synchronization if at least one writer is involved.

(I guess Jonas intended to avoid a complicate answer, but let me complicate it for you ;-)

... and the AnsiString has refcount = 1. If you access the string through a by-value parameter or assign it to a temporary variable, you're safe too. (unless, of course, some screwed code change the contents of the string in-place - e.g. with a typecast to pchar or some other pointer)

-Flávio