Discussion:
Easiest way to "case" strings
Reenen Laurie
2009-03-21 09:35:22 UTC
Permalink
Hi,

I'm sure most of you have had this... is there an easy way to have a case
statement that's based on "strings" rather than ordinal types. Is there
somewhere a shortcut?

The only solution I can think of is defining constants with strings and
ordinal types...

What I'd like to do is:
case fruit of:
'apple' :
'pear' :
'banana':
'grape':
else

end;

So the only solution I can think of is
const fruitlist = (apple,pear,banana,grape);
fruitstrings = ('apple','pear','banana','grape');

and then...

for i := apple to grape do
if fruit {string} = fruitstrings[i] then fruitvar := i;

case fruitvar of
apple :
pear :
banana :
grape :
else
end;

Any easier solutions to trying to run a case on a "string"?

Regards,
-Reenen
--
o__
,_.>/ _
(_)_\(_)_______
...speed is good
_______________
I believe five out of four people have a problem with fractions.
Michael Van Canneyt
2009-03-21 09:59:12 UTC
Permalink
Post by Reenen Laurie
Hi,
I'm sure most of you have had this... is there an easy way to have a case
statement that's based on "strings" rather than ordinal types. Is there
somewhere a shortcut?
The only solution I can think of is defining constants with strings and
ordinal types...
else
end;
So the only solution I can think of is
const fruitlist = (apple,pear,banana,grape);
fruitstrings = ('apple','pear','banana','grape');
and then...
for i := apple to grape do
if fruit {string} = fruitstrings[i] then fruitvar := i;
case fruitvar of
else
end;
Any easier solutions to trying to run a case on a "string"?
Well, you could try this:

Program doit;

uses sysutils;

Function WordCase(Const S : String; Const Options : Array of string) : Integer;

begin
Result:=High(Options);
While (Result>=0) and (COmpareText(S,Options[Result])<>0) do
Dec(Result);
end;

begin
Case WordCase(Paramstr(1),['zero','one','two','three']) of
0 : Writeln('zero found');
1 : Writeln('One found');
2 : Writeln('Two found');
3 : Writeln('Three found');
else
Writeln('Unknown case : ',paramstr(1));
end;
end.

It works for me :-)

Michael.
Vincent Snijders
2009-03-21 10:03:13 UTC
Permalink
Post by Reenen Laurie
Hi,
I'm sure most of you have had this... is there an easy way to have a
case statement that's based on "strings" rather than ordinal types. Is
there somewhere a shortcut?
You can use stringcase:
http://lazarus-ccr.sourceforge.net/docs/lcl/lclproc/stringcase.html

Unfortunately without example. It is used in the Lazarus sources, so
maybe you find out how to use it from there.

Vincent
Alexander Klenin
2009-03-21 12:39:48 UTC
Permalink
On Sat, Mar 21, 2009 at 20:03, Vincent Snijders
Post by Vincent Snijders
Post by Reenen Laurie
Hi,
I'm sure most of you have had this... is there an easy way to have a
case statement that's based on "strings" rather than ordinal types.  Is
there somewhere a shortcut?
http://lazarus-ccr.sourceforge.net/docs/lcl/lclproc/stringcase.html
Unfortunately without example. It is used in the Lazarus sources, so
maybe you find out how to use it from there.
Hm, this function duplicates AnsiIndexStr / AnsiIndexText which are
Delphi-compatible. Is there a reason for its existence?
--
Alexander S. Klenin
Marc Weustink
2009-03-21 13:37:10 UTC
Permalink
Post by Alexander Klenin
On Sat, Mar 21, 2009 at 20:03, Vincent Snijders
Post by Vincent Snijders
Post by Reenen Laurie
Hi,
I'm sure most of you have had this... is there an easy way to have a
case statement that's based on "strings" rather than ordinal types. Is
there somewhere a shortcut?
http://lazarus-ccr.sourceforge.net/docs/lcl/lclproc/stringcase.html
Unfortunately without example. It is used in the Lazarus sources, so
maybe you find out how to use it from there.
Hm, this function duplicates AnsiIndexStr / AnsiIndexText which are
Delphi-compatible. Is there a reason for its existence?
At the time I wrote StringCase, AnsiIndexStr / AnsiIndexText were
unknown to me. I wonder even if they existed at that time. When did
delphi introduce them ? (just a coincidence, I just "discovered" them
last week)

Marc
Alexander Klenin
2009-03-21 14:20:50 UTC
Permalink
Post by Marc Weustink
At the time I wrote StringCase, AnsiIndexStr / AnsiIndexText were
unknown to me. I wonder even if they existed at that time. When did
delphi introduce them ? (just a coincidence, I just "discovered" them
last week)
They definitely exist in Delphi 7.
Google search suggests they were introduced around Delphi 5.
--
Alexander S. Klenin
Marc Weustink
2009-03-21 14:39:23 UTC
Permalink
Post by Alexander Klenin
Post by Marc Weustink
At the time I wrote StringCase, AnsiIndexStr / AnsiIndexText were
unknown to me. I wonder even if they existed at that time. When did
delphi introduce them ? (just a coincidence, I just "discovered" them
last week)
They definitely exist in Delphi 7.
Google search suggests they were introduced around Delphi 5.
That might explain, the first incarnation of StringCase was written in D4

Marc
Howard Page-Clark
2009-03-21 22:57:20 UTC
Permalink
On Sat, 21 Mar 2009 15:39:23 +0100
Post by Marc Weustink
Post by Alexander Klenin
Post by Marc Weustink
At the time I wrote StringCase, AnsiIndexStr / AnsiIndexText were
unknown to me. I wonder even if they existed at that time. When did
delphi introduce them ? (just a coincidence, I just "discovered"
them last week)
They definitely exist in Delphi 7.
Google search suggests they were introduced around Delphi 5.
That might explain, the first incarnation of StringCase was written in D4
IndexStr() and AnsiIndexStr() were introduced in the then new StrUtils
unit that shipped with BDS 3.0 (Delphi 2005). There is no StrUtils
unit, or access to these functions in my Delphi 5 installation.

Howard
Alexander Klenin
2009-03-22 06:14:09 UTC
Permalink
Post by Howard Page-Clark
IndexStr() and AnsiIndexStr() were introduced in the then new StrUtils
unit that shipped with BDS 3.0 (Delphi 2005). There is no StrUtils
unit, or access to these functions in my Delphi 5 installation.
Are you sure? I did not found Delphi 5 installation, but managed to
install Delphi 6 --
StrUtils unit is at C:\Program
Files\Borland\Delphi6\Source\Rtl\Common\StrUtils.pas
and it does contain AnsiIndex* functions.
Copyright header says "1995-2001" which I think dates at least the
unit itself all the way
back to Delphi 1.
--
Alexander S. Klenin
Howard Page-Clark
2009-03-22 09:08:57 UTC
Permalink
On Sun, 22 Mar 2009 16:14:09 +1000
Post by Alexander Klenin
Post by Howard Page-Clark
IndexStr() and AnsiIndexStr() were introduced in the then new
StrUtils unit that shipped with BDS 3.0 (Delphi 2005). There is no
StrUtils unit, or access to these functions in my Delphi 5
installation.
Are you sure? I did not found Delphi 5 installation, but managed to
install Delphi 6 --
StrUtils unit is at C:\Program
Files\Borland\Delphi6\Source\Rtl\Common\StrUtils.pas
and it does contain AnsiIndex* functions.
Copyright header says "1995-2001" which I think dates at least the
unit itself all the way
back to Delphi 1.
I don't have Delphi 6 - clearly the functions are present there. I was
wrong about the timing of the introduction of the StrUtils unit.
Maybe my version of Delphi 5 Pro is incomplete or damaged, but I can
confirm it does not have the StrUtils unit (or obviously the functions
contained there).

Howard
Lee Jenkins
2009-03-21 14:28:20 UTC
Permalink
Post by Vincent Snijders
Post by Reenen Laurie
Hi,
I'm sure most of you have had this... is there an easy way to have a
case statement that's based on "strings" rather than ordinal types. Is
there somewhere a shortcut?
http://lazarus-ccr.sourceforge.net/docs/lcl/lclproc/stringcase.html
Unfortunately without example. It is used in the Lazarus sources, so
maybe you find out how to use it from there.
Vincent
Can anyone say why there is no string case statement in Object Pascal? I've
always wondered about this as sometimes it hard to avoid 10-20 If..then..else
if.... statements.

Would the compiled code of a string case statement even be any more efficient or
is the benefit mostly in code readability?

--
Warm Regards,

Lee
Michael Van Canneyt
2009-03-21 14:57:41 UTC
Permalink
Post by Lee Jenkins
Post by Vincent Snijders
Post by Reenen Laurie
Hi,
I'm sure most of you have had this... is there an easy way to have a
case statement that's based on "strings" rather than ordinal types. Is
there somewhere a shortcut?
http://lazarus-ccr.sourceforge.net/docs/lcl/lclproc/stringcase.html
Unfortunately without example. It is used in the Lazarus sources, so
maybe you find out how to use it from there.
Vincent
Can anyone say why there is no string case statement in Object Pascal? I've
always wondered about this as sometimes it hard to avoid 10-20 If..then..else
if.... statements.
Would the compiled code of a string case statement even be any more efficient or
is the benefit mostly in code readability?
In the case of strings, it would mostly be code readability. For ordinal
types, a case statement can be optimized using jump tables.

Michael.
Flávio Etrusco
2009-03-21 15:15:05 UTC
Permalink
Post by Michael Van Canneyt
Can anyone say why there is no string case statement in Object Pascal?  I've
always wondered about this as sometimes it hard to avoid 10-20 If..then..else
if.... statements.
Would the compiled code of a string case statement even be any more efficient or
is the benefit mostly in code readability?
In the case of strings, it would mostly be code readability. For ordinal
types, a case statement can be optimized using jump tables.
Michael.
A string case could be optimized with compile-time hashes or something else.

-Flávio
Michael Van Canneyt
2009-03-21 15:24:02 UTC
Permalink
Post by Flávio Etrusco
Post by Michael Van Canneyt
Can anyone say why there is no string case statement in Object Pascal?  I've
always wondered about this as sometimes it hard to avoid 10-20 If..then..else
if.... statements.
Would the compiled code of a string case statement even be any more efficient or
is the benefit mostly in code readability?
In the case of strings, it would mostly be code readability. For ordinal
types, a case statement can be optimized using jump tables.
Michael.
A string case could be optimized with compile-time hashes or something else.
Even so, there are some serious issues with a string 'case' as a language construct:
- What about encodings ?
- Should it be case sensitive or not ?
I don't think that these can be solved in a satisfying manner on a language level.

Michael.
Reenen Laurie
2009-03-21 15:38:30 UTC
Permalink
It should be space and case sensitive... the programmer can add
trim(lowercase(s)) to the case argument...

Encodings are going to make it much trickier... but whatever encoding is
supported in the IDE.
Post by Lee Jenkins
Post by Flávio Etrusco
Post by Michael Van Canneyt
Post by Lee Jenkins
Can anyone say why there is no string case statement in Object Pascal?
I've
Post by Flávio Etrusco
Post by Michael Van Canneyt
Post by Lee Jenkins
always wondered about this as sometimes it hard to avoid 10-20
If..then..else
Post by Flávio Etrusco
Post by Michael Van Canneyt
Post by Lee Jenkins
if.... statements.
Would the compiled code of a string case statement even be any more
efficient or
Post by Flávio Etrusco
Post by Michael Van Canneyt
Post by Lee Jenkins
is the benefit mostly in code readability?
In the case of strings, it would mostly be code readability. For
ordinal
Post by Flávio Etrusco
Post by Michael Van Canneyt
types, a case statement can be optimized using jump tables.
Michael.
A string case could be optimized with compile-time hashes or something
else.
- What about encodings ?
- Should it be case sensitive or not ?
I don't think that these can be solved in a satisfying manner on a language level.
Michael.
_______________________________________________
Lazarus mailing list
http://www.lazarus.freepascal.org/mailman/listinfo/lazarus
--
o__
,_.>/ _
(_)_\(_)_______
...speed is good
_______________
I believe five out of four people have a problem with fractions.
Alexander Klenin
2009-03-21 16:27:03 UTC
Permalink
Post by Michael Van Canneyt
- What about encodings ?
Nothing about them, just compare byte-by-byte, as usual string comparison do.
Post by Michael Van Canneyt
- Should it be case sensitive or not ?
Of course no.
Post by Michael Van Canneyt
I don't think that these can be solved in a satisfying manner on a language level.
Generally, I feel that FPC is a bit too conservative. I understand
that a healthy dose if
skepticism is a good thing for language design, but IMHO it was taken
too far lately.
--
Alexander S. Klenin
Hans-Peter Diettrich
2009-03-21 19:44:28 UTC
Permalink
Post by Alexander Klenin
Generally, I feel that FPC is a bit too conservative. I understand
that a healthy dose if
skepticism is a good thing for language design, but IMHO it was taken
too far lately.
Many Delphi extensions to the Pascal language break fundamental design
rules. It's bad enough that FPC (and Lazarus) has to support such
aberrations for compatibility reasons, but further extensions should be
added very carefully, taking into account the design and experiences
with the successor languages (Modula, Oberon...).

DoDi
Marco van de Voort
2009-03-23 21:03:43 UTC
Permalink
Post by Alexander Klenin
Of course no.
Post by Michael Van Canneyt
I don't think that these can be solved in a satisfying manner on a language level.
Generally, I feel that FPC is a bit too conservative. I understand
that a healthy dose if
skepticism is a good thing for language design, but IMHO it was taken
too far lately.
Well, you can nearly impossibly miss the sliding slope there. First just
strings, then hashing to speed it up, then wildcards, then demand for regex
etc. And everytime the same references to other interpreted languages that
do such things.

In general the Wirthian philosophy was limitation to the basics, and
Pascal's direct successor language (modula2) is actually smaller.
Alexander Klenin
2009-03-24 04:35:11 UTC
Permalink
Post by Marco van de Voort
Well, you can nearly impossibly miss the sliding slope there. First just
strings, then hashing to speed it up, then wildcards, then demand for regex
etc.
This is generic argument applicable to any language feature.
"Sliding slopes" are everywhere, so the safest course of action is not
to move at all.
This is what I am ranting about, excessive conservatism leading to a stagnation.
Post by Marco van de Voort
And everytime the same references to other interpreted languages that do such things.
Eh, "other interpreted"? Pascal is compiled, as you surely know.
Post by Marco van de Voort
In general the Wirthian philosophy was limitation to the basics, and
Pascal's direct successor language (modula2) is actually smaller.
I already answered this. Modula and Oberon are a direct successors of Pascal,
but so is Object Pascal. For better or worse, Object Pascal has taken
another course,
and I don't think it is a good move to retrofit minimalist philosophy
to Object Pascal now.

Otherwise, we should start by removing built-in Strings -- they are against
this philosophy too (and were criticized for that).
--
Alexander S. Klenin
Florian Klaempfl
2009-03-24 12:40:58 UTC
Permalink
Post by Alexander Klenin
Post by Marco van de Voort
Well, you can nearly impossibly miss the sliding slope there. First just
strings, then hashing to speed it up, then wildcards, then demand for regex
etc.
This is generic argument applicable to any language feature.
"Sliding slopes" are everywhere, so the safest course of action is not
to move at all.
This is what I am ranting about, excessive conservatism leading to a stagnation.
You can rant about it if we reject a patch adding case with strings ;)

I'am quite sure, a good patch (clear definition of the scope, support
for all string types, clear definition how the strings are interpreted,
tests) to implement it won't be rejected.
Alexander Klenin
2009-03-24 13:47:28 UTC
Permalink
Post by Florian Klaempfl
You can rant about it if we reject a patch adding case with strings ;)
I'am quite sure, a good patch (clear definition of the scope, support
for all string types, clear definition how the strings are interpreted,
tests) to implement it won't be rejected.
That's refreshing, thanks ;-) From other answers I've got a feeling that
such a patch would be rejected "in principle".
Well, I definitely do not have resources for that now, but maybe
in a few months...
--
Alexander S. Klenin
Florian Klaempfl
2009-03-24 14:10:01 UTC
Permalink
Post by Alexander Klenin
Post by Florian Klaempfl
You can rant about it if we reject a patch adding case with strings ;)
I'am quite sure, a good patch (clear definition of the scope, support
for all string types, clear definition how the strings are interpreted,
tests) to implement it won't be rejected.
That's refreshing, thanks ;-) From other answers I've got a feeling that
such a patch would be rejected "in principle".
Well, the thumb rule is simple: the people who code decide ;)
Alexander Klenin
2009-03-21 15:03:20 UTC
Permalink
Can anyone say why there is no string case statement in Object Pascal?  I've
always wondered about this as sometimes it hard to avoid 10-20 If..then..else
if.... statements.
I'd say it is because nobody contributed it ;-)
Would the compiled code of a string case statement even be any more efficient or
is the benefit mostly in code readability?
Both. It can be implemented as prefix tree,
giving O(MaxLength) instead of O(MaxLength*NumberOfCases) time _and_
a much better readability/maintainability.
--
Alexander S. Klenin
Hans-Peter Diettrich
2009-03-21 19:36:51 UTC
Permalink
Post by Alexander Klenin
Post by Lee Jenkins
Can anyone say why there is no string case statement in Object Pascal? I've
always wondered about this as sometimes it hard to avoid 10-20 If..then..else
if.... statements.
I'd say it is because nobody contributed it ;-)
There exist too many options with string comparison. In a table lookup
the compare method can be supplied by the application, in a case
statement this would require another syntax extension.

DoDi
Alexander Klenin
2009-03-22 06:06:32 UTC
Permalink
On Sun, Mar 22, 2009 at 05:36, Hans-Peter Diettrich
Post by Hans-Peter Diettrich
There exist too many options with string comparison. In a table lookup
the compare method can be supplied by the application, in a case
statement this would require another syntax extension.
There are also many ways to implement strings and dynamic arrays --
but this did not stopped Object Pascal author from adding them,
and I think he was right, even if some of his design decisions are suboptimal.
This "consider all roads then choose none" approach will, obviously,
never allow you to get anywhere ;-)
Post by Hans-Peter Diettrich
Many Delphi extensions to the Pascal language break fundamental design
rules. It's bad enough that FPC (and Lazarus) has to support such
aberrations for compatibility reasons,
I agree that some extensions were suboptimally designed, in particular
dynamic arrays,
but "aberrations"? Can you give an example?
Post by Hans-Peter Diettrich
but further extensions should be added very carefully,
Yes, but still they should be added -- that was my point.
Post by Hans-Peter Diettrich
taking into account the design and experiences
with the successor languages (Modula, Oberon...).
While I deeply respect Wirth's contributions to programming language design,
I think Modula and especially Oberon are not the best sources for inspiration.
Object Pascal has log ago taken different direction -- for example,
if we "take into account" Oberon, then we should, as a first step,
remove strings, classes, virtual functions and "for" loop.
I do not think this is a good way to evolve FPC ;-)
--
Alexander S. Klenin
Hans-Peter Diettrich
2009-03-22 08:07:02 UTC
Permalink
Post by Alexander Klenin
Post by Hans-Peter Diettrich
Many Delphi extensions to the Pascal language break fundamental design
rules. It's bad enough that FPC (and Lazarus) has to support such
aberrations for compatibility reasons,
I agree that some extensions were suboptimally designed, in particular
dynamic arrays,
but "aberrations"? Can you give an example?
Delphi 2 (or 3?) was the last version with a grammar for the language.
After that version the supplied "OPL grammar" is neither correct nor
complete, the language is no more LL(1).
Post by Alexander Klenin
While I deeply respect Wirth's contributions to programming language design,
I think Modula and especially Oberon are not the best sources for inspiration.
I dare to disagree.
Post by Alexander Klenin
Object Pascal has log ago taken different direction -- for example,
if we "take into account" Oberon, then we should, as a first step,
remove strings, classes, virtual functions and "for" loop.
I do not think this is a good way to evolve FPC ;-)
Please note that I don't ask for Modula or Oberon compatibility, even if
it were fine to have such modes.

DoDi
Alexander Klenin
2009-03-22 09:18:05 UTC
Permalink
On Sun, Mar 22, 2009 at 18:07, Hans-Peter Diettrich
Post by Hans-Peter Diettrich
Delphi 2 (or 3?) was the last version with a grammar for the language.
After that version the supplied "OPL grammar" is neither correct nor
complete, the language is no more LL(1).
It is historically interesting, but does it really matter?
The important characteristic of the syntax is its convenience to humans,
and if that requires slightly more work from the compiler, then so be it.
AFAIK, most modern compilers moved to recursive descent parsers
due to similar reasons.
Post by Hans-Peter Diettrich
Post by Alexander Klenin
While I deeply respect Wirth's contributions to programming language design,
I think Modula and especially Oberon are not the best sources for inspiration.
I dare to disagree.
Present your examples then ;-)
Post by Hans-Peter Diettrich
Post by Alexander Klenin
Object Pascal has log ago taken different direction -- for example,
if we "take into account" Oberon, then we should, as a first step,
remove strings, classes, virtual functions and "for" loop.
I do not think this is a good way to evolve FPC ;-)
Please note that I don't ask for Modula or Oberon compatibility, even if
it were fine to have such modes.
Of course, I understand that. My examples were aimed not at direct
compatibility, but the spirit of minimalism that was the driving force
of the Modula/Oberon design.
Besides that, what useful features do you think
Object Pascal / FPC might take from Oberon?
--
Alexander S. Klenin
Hans-Peter Diettrich
2009-03-22 20:18:39 UTC
Permalink
Post by Alexander Klenin
Post by Hans-Peter Diettrich
Delphi 2 (or 3?) was the last version with a grammar for the language.
After that version the supplied "OPL grammar" is neither correct nor
complete, the language is no more LL(1).
It is historically interesting, but does it really matter?
I'd call it serious, when a single semicolon can change the meaning of
the source code (before a case else).
Post by Alexander Klenin
The important characteristic of the syntax is its convenience to humans,
and if that requires slightly more work from the compiler, then so be it.
AFAIK, most modern compilers moved to recursive descent parsers
due to similar reasons.
Just hand written recursive descent parsers leave room for any kind of
irregular behaviour :-(
Post by Alexander Klenin
Post by Hans-Peter Diettrich
Post by Alexander Klenin
While I deeply respect Wirth's contributions to programming language design,
I think Modula and especially Oberon are not the best sources for inspiration.
I dare to disagree.
Present your examples then ;-)
I don't want to go into details here. The design of a language is so
complex, most decisions depend on others, and they must fit all together.
Post by Alexander Klenin
Besides that, what useful features do you think
Object Pascal / FPC might take from Oberon?
More important is what *not* should be taken from other languages.

DoDi
Marco van de Voort
2009-03-25 14:23:44 UTC
Permalink
This post might be inappropriate. Click to display it.
Alexander Klenin
2009-03-26 00:28:50 UTC
Permalink
Post by Marco van de Voort
Since we are close to 20 stringtypes + conversions now, I doubt that this is
really the problem.
Yes, I agree that the string types in FPC are a mess,
and judging by recent discussion, they are planned to became worse.
It is fortunate that Lazarus introduces a little bit of sanity here.
Post by Marco van de Voort
What problem does "for in" really solve?
Lack of iterators.
Post by Marco van de Voort
Is having 6 levels of information
hiding (private,public,strict protected, strict private,protected,published)
or are the strict* ones just to stop the whining of people that come from
other languages?
No, it is not necessary, but handy sometimes. I agree that these are
not a big deal,
and FPC can live without them quite fine, but they do not break anything either.
Post by Marco van de Voort
What is the function of being able to add methods to records?
Not much, I agree, given the existence of objects. It would be better to do that
instead of introducing 'object' keyword, but that decision was made
back in the days
of Borland Pascal.
Post by Marco van de Voort
What is the real use of duplicating const type and var as nested variants
inside classes?
Namespace management.
Post by Marco van de Voort
http://www.stack.nl/~marcov/delphilater.txt
Thanks, that is interesting discussion. I will post my thoughts on
that in a separate mail.
Post by Marco van de Voort
The old rule used to be that
- it should make something possible that is not doable otherwise.
Like strict private/protected?
Post by Marco van de Voort
- _or_ it should be a construct that is used so much that timesavings are
 noticable
Like for ... in?
Post by Marco van de Voort
And string-case for my feeling belongs in neither. It is just about racking
up bullet lists in language wars.
Well, there is another important design principle.
It is sometimes called "orthogonality" -- it means that existing
language features
can be combined in any way, with as little limitation as possible.
Since string was introduced as built-in "scalar" type with defined equality,
lack of 'case' support can be viewed as a design bug.
--
Alexander S. Klenin
Flávio Etrusco
2009-03-26 00:46:30 UTC
Permalink
Post by Alexander Klenin
Post by Marco van de Voort
What problem does "for in" really solve?
Lack of iterators.
Also, Pascal is all about readability and maintainability, so avoiding
a redundant variable declaration and attribution, and the opportunity
of people misusing and mis-reusing a counter variable is pretty worth
IMO.
Post by Alexander Klenin
Post by Marco van de Voort
Is having 6 levels of information
hiding (private,public,strict protected, strict private,protected,published)
or are the strict* ones just to stop the whining of people that come from
other languages?
No, it is not necessary, but handy sometimes. I agree that these are
not a big deal,
and FPC can live without them quite fine, but they do not break anything either.
It's almost necessary, if you want to implement real safe code and
don't wanna use tens of units.
Post by Alexander Klenin
Post by Marco van de Voort
What is the function of being able to add methods to records?
Not much, I agree, given the existence of objects. It would be better to do that
instead of introducing 'object' keyword, but that decision was made
back in the days
of Borland Pascal.
Indeed, not much, but the memory savings can be really interesting in
some situations.


-Flávio
Hans-Peter Diettrich
2009-03-26 08:29:39 UTC
Permalink
Post by Flávio Etrusco
Post by Alexander Klenin
Post by Marco van de Voort
What is the function of being able to add methods to records?
Not much, I agree, given the existence of objects. It would be better to do that
instead of introducing 'object' keyword, but that decision was made
back in the days
of Borland Pascal.
Indeed, not much, but the memory savings can be really interesting in
some situations.
The storage of class instances can be modified by overriding the
according methods. I did so for arrays of instances, and it worked fine
in Delphi. With some tricks it should be possible to have both static
and dynamic allocation, for the same class type.

I also found at least one use for records with methods, in the emulation
of C structs with bitfields or unions. For that matter 'object' and
properties came in handy.

IMO one difference between class and record will stay that records
cannot have virtual methods (in Delphi), due to the inlined VMT
pointers. Another difference will be heritage - records are not extensible.

BTW, 'object' became deprecated (in Delphi) only when the
reference-counted data types have been introduced. Delphi (willingly)
doesn't support properly objects inheriting from another object type, in
which case only the top level type is initialized and finalized
properly. I wonder why the same construct with records (nested in
records) has been made work, then.

DoDi
Graeme Geldenhuys
2009-03-26 11:43:22 UTC
Permalink
On Thu, Mar 26, 2009 at 10:29 AM, Hans-Peter Diettrich
Post by Hans-Peter Diettrich
I also found at least one use for records with methods, in the emulation
of C structs with bitfields or unions. For that matter 'object' and
properties came in handy.
Yup, I still use 'object' often. As in the case of fpGUI Toolkit's
TfpgRect type.

TfpgRect = object // not class for static allocations
Top: TfpgCoord;
Left: TfpgCoord;
Width: TfpgCoord;
Height: TfpgCoord;
procedure SetRect(aleft, atop, awidth, aheight: TfpgCoord);
function Bottom: TfpgCoord;
function Right: TfpgCoord;
procedure SetBottom(Value: TfpgCoord);
procedure SetRight(Value: TfpgCoord);
end;

And as the comment says, I use 'object' instead of class, so I don't
explicitly have to create an instance, I can just declare a variable
and use it.


Regards,
- Graeme -


_______________________________________________
fpGUI - a cross-platform Free Pascal GUI toolkit
http://opensoft.homeip.net/fpgui/
Vincent Snijders
2009-03-26 08:34:24 UTC
Permalink
Post by Alexander Klenin
Post by Marco van de Voort
http://www.stack.nl/~marcov/delphilater.txt
Thanks, that is interesting discussion. I will post my thoughts on
that in a separate mail.
On the fpc-pascal mailing list or maybe the fpc-decel mailing list, I presume.

Vincent
Hans-Peter Diettrich
2009-03-26 07:56:36 UTC
Permalink
Post by Alexander Klenin
Since string was introduced as built-in "scalar" type with defined equality,
lack of 'case' support can be viewed as a design bug.
IMO strings are similarly "scalar" as are floating point numbers, with
regards to 'case'.

DoDi
Alexander Klenin
2009-03-26 09:48:38 UTC
Permalink
On Thu, Mar 26, 2009 at 17:56, Hans-Peter Diettrich
Post by Hans-Peter Diettrich
Post by Alexander Klenin
Since string was introduced as built-in "scalar" type with defined equality,
lack of 'case' support can be viewed as a design bug.
IMO strings are similarly "scalar" as are floating point numbers, with
regards to 'case'.
Note that I said "with defined equality". The reason 'case' should not include
floating point numbers is that equality if not usefully defined for them.
--
Alexander S. Klenin
Hans-Peter Diettrich
2009-03-27 00:02:57 UTC
Permalink
Post by Alexander Klenin
Post by Hans-Peter Diettrich
Post by Alexander Klenin
Since string was introduced as built-in "scalar" type with defined equality,
lack of 'case' support can be viewed as a design bug.
IMO strings are similarly "scalar" as are floating point numbers, with
regards to 'case'.
Note that I said "with defined equality". The reason 'case' should not include
floating point numbers is that equality if not usefully defined for them.
The same for strings, where mere binary (case sensitive) equality often
is useless.

Furthermore Pascal 'case' supports ranges, which deserve a stricter
order than only equality. Then the sort order of strings also depends on
the encoding (codepage, MBCS, UTF...).

And last not least strings IMO are complex types (array of char), as
they have been in Wirth Pascal. The order of a comparison of ordinals is
O(1), whereas string comparison is O(n).

DoDi
Alexander Klenin
2009-03-27 08:51:34 UTC
Permalink
On Fri, Mar 27, 2009 at 10:02, Hans-Peter Diettrich
Post by Hans-Peter Diettrich
Post by Alexander Klenin
Note that I said "with defined equality". The reason 'case' should not include
floating point numbers is that equality if not usefully defined for them.
The same for strings, where mere binary (case sensitive) equality often
is useless.
Well, we should get rid of 'operator = (String, String)' then ;-)
Seriously, I think you are exaggerating here.
Post by Hans-Peter Diettrich
Furthermore Pascal 'case' supports ranges, which deserve a stricter
order than only equality. Then the sort order of strings also depends on
the encoding (codepage, MBCS, UTF...).
Heh, I indeed forgot about ranges. Their existence actually allows to implement
a useful 'case' for floating point types, so I now support a 'case of
real' also.
As for sorting order -- just do what built-in inequality does, there
is no reason
to deviate.
Post by Hans-Peter Diettrich
And last not least strings IMO are complex types (array of char), as
they have been in Wirth Pascal.
Yes, but Object Pascal choose to _not_ follow
Wirth's design here, so in Object Pascal strings are not 'array of char'.
Post by Hans-Peter Diettrich
The order of a comparison of ordinals is
O(1), whereas string comparison is O(n).
Still, to compare given string with length n with m constant strings,
O(n + m) time is sufficient, which, as I already stated, is another reason
to implement string 'case' ;-)
Post by Hans-Peter Diettrich
Post by Alexander Klenin
[regarding 'case of string']
Post by Marco van de Voort
Yes. But since this is not a simple type, but a complex type, it goes to a
different class. If that is your argument, make sure it works for arrays, records,
classes, interfaces and the other complex types too.
I definitely agree that 'case' should work for classes --
perhaps even more important than for strings. For records and static arrays
it could be implemented, but the value of such feature would be truly marginal.
There is indeed a problem with ranges of classes.
Maybe interpret them using inheritance as a partial ordering?
E.g. TPersistent..TComponent is ok, but TButton..TDataset is error?
Post by Hans-Peter Diettrich
I.e. what's the literal value and representation of the case label for an record?
Record constant of course.
Post by Hans-Peter Diettrich
What for 'RecA..RecX:'?
I'd say it is RecA.F .. RecX.F for each record field, field recursively.

As I already said, I am not really in favor of 'case of record',
although you have already
convinced me to support the 'case of real'. Still, here is a possible
usage sample for the former:

case MyPoint of
(x:-1, y:-1): ProcessEmptyPoint;
(x:0, y:0)..(x:100, y:100): ProcessPoint;
else InvalidPoint;
end.
--
Alexander S. Klenin
Marco van de Voort
2009-03-26 08:59:15 UTC
Permalink
Post by Alexander Klenin
Post by Marco van de Voort
What problem does "for in" really solve?
Lack of iterators.
No it doesn't IMHO. And I assume that by "lack of iterators" you mean
in-language iterators?
Post by Alexander Klenin
Post by Marco van de Voort
Is having 6 levels of information
hiding (private,public,strict protected, strict private,protected,published)
or are the strict* ones just to stop the whining of people that come from
other languages?
No, it is not necessary, but handy sometimes.
One can give this "handy" moniker to every randomly thought up with an
example that shortens some random code fragment. IMHO it is meaningless.

It is about what a feature makes possible, and, in the rare cases of
synctactic sugar, how often it is used.

I'm also not entirely happy with the way dynamic arrays are set up. They
seem to be made mostly for COM use, the mandatory 0-basedness is unpascal
like etc.

However after initial resist, I started to use them, because they simplify a
lot of menial pointer code for simple dynamic memory use.

I can live with such an argumentation. However, if I take the case of string
as example, I see only very rare occasions, and I wouldn't even use case of
string because it is so limited. If suddenly the cases wouldn't be
compiletime anymore (because they become user configurable or localised
values) you have to morph the entire block.
Post by Alexander Klenin
I agree that these are not a big deal, and FPC can live without them quite
fine, but they do not break anything either.
I don't see an automatical need to add features. Featuritis is a disease,
not a benefit. It limits the room (and increases the work needed) to add
features that are really needed, because of implementation complexity and
backwards compatibility concerns
Post by Alexander Klenin
Post by Marco van de Voort
What is the function of being able to add methods to records?
Not much, I agree, given the existence of objects. It would be better to
do that instead of introducing 'object' keyword, but that decision was
made back in the days of Borland Pascal.
(there is some discussion that borland actually did this to limit the scope
of duck typing that is used for for..in and operator overloading. I never
studied that in detail)
Post by Alexander Klenin
Post by Marco van de Voort
What is the real use of duplicating const type and var as nested variants
inside classes?
Namespace management.
They copied it from languages that have class as the only namespace. However
the unit based Pascal concept already has units and the unit namespace to
identify between similarly global symbols.

So that is not enough reason. At least for me.
Post by Alexander Klenin
Post by Marco van de Voort
http://www.stack.nl/~marcov/delphilater.txt
Thanks, that is interesting discussion. I will post my thoughts on
that in a separate mail.
I assume you read

http://www.freepascal.org/faq.var#extensionselect
Post by Alexander Klenin
Post by Marco van de Voort
The old rule used to be that
- it should make something possible that is not doable otherwise.
Like strict private/protected?
No. Because every feature makes something doable. IOW look less to the
code-construct but more to what you want to do with it.

Personally I don't believe in micromanagement of visibility levels, and even
if I did, I wanted a more dynamic way to do this (C# afaik goes more that way with
the possibility to tag functions using user defined properties), instead of
ad-hoc expanding visibility specifiers.
Post by Alexander Klenin
Post by Marco van de Voort
- _or_ it should be a construct that is used so much that timesavings are
??noticable
Like for ... in?
I never used in under Delphi except to iterate over sets.
Post by Alexander Klenin
Post by Marco van de Voort
And string-case for my feeling belongs in neither. It is just about racking
up bullet lists in language wars.
Well, there is another important design principle. It is sometimes called
"orthogonality" -- it means that existing language features can be
combined in any way, with as little limitation as possible.
Yes. But since this is not a simple type, but a complex type, it goes to a
different class. If that is your argument, make sure it works for arrays, records,
classes, interfaces and the other complex types too.
Post by Alexander Klenin
Since string was introduced as built-in "scalar" type with defined
equality, lack of 'case' support can be viewed as a design bug.
I don't see string as a scalar type. It is an array or complex type IMHO.
Florian Klaempfl
2009-03-26 09:10:31 UTC
Permalink
Post by Marco van de Voort
Post by Alexander Klenin
Post by Marco van de Voort
And string-case for my feeling belongs in neither. It is just about racking
up bullet lists in language wars.
Well, there is another important design principle. It is sometimes called
"orthogonality" -- it means that existing language features can be
combined in any way, with as little limitation as possible.
Yes. But since this is not a simple type, but a complex type, it goes to a
different class. If that is your argument, make sure it works for arrays, records,
classes, interfaces and the other complex types too.
Actually, case is not defined for all types but for all ordinal types ;)
Alexander Klenin
2009-03-26 10:29:42 UTC
Permalink
Post by Marco van de Voort
Post by Alexander Klenin
Post by Marco van de Voort
What problem does "for in" really solve?
Lack of iterators.
No it doesn't IMHO.
This is really nice argument ;-) Well, it _should_ solve it.
If it does not, it must be extended of implemented differently.
I definitely do not argue in favor of blindly copying Delphi features.
Post by Marco van de Voort
And I assume that by "lack of iterators" you mean in-language iterators?
Of course. What else?
Post by Marco van de Voort
One can give this "handy" moniker to every randomly thought up with an
example that shortens some random code fragment. IMHO it is meaningless.
As I said, I agree that the case for 'strict' visibility is rather weak.
However, it still has practical uses. For a recent example: Lazarus contains
some extremely overbloated source files, some more than 10000 lines long,
with dozens of classes.
The task of refactoring them into a reasonable set of units is daunting.
It would be made easier if I were able to first isolate classes inside the unit
with 'strict' visibility specifiers to make sure nothing breaks
when I move those classes away.
Post by Marco van de Voort
I'm also not entirely happy with the way dynamic arrays are set up. They
seem to be made mostly for COM use, the mandatory 0-basedness is unpascal
like etc.
0-basedness, althout indeed "unpascal" is just a nuisance.
The real problem of dynamic arrays is O(n^2) growing time.
Is they, like TList, contained separate 'Length" and 'Capacity'
fields, they would be
much more useful -- to the point that TList could be totally superseded.
Post by Marco van de Voort
I can live with such an argumentation. However, if I take the case of string
as example, I see only very rare occasions, and I wouldn't even use case of
string because it is so limited. If suddenly the cases wouldn't be
compiletime anymore (because they become user configurable or localised
values) you have to morph the entire block.
If they are not constants, the user should use 'if', this is obvious.
And of course cases should not be localised.
I am talking about such use cases as tokenizers and protocol handlers.
Post by Marco van de Voort
Post by Alexander Klenin
Post by Marco van de Voort
What is the real use of duplicating const type and var as nested variants
inside classes?
Namespace management.
They copied it from languages that have class as the only namespace. However
the unit based Pascal concept already has units and the unit namespace to
identify between similarly global symbols.
When the codebase becomes big enough, more than one level of hierarchy
becomes useful.
Post by Marco van de Voort
Post by Alexander Klenin
Like for ... in?
I never used in under Delphi except to iterate over sets.
Well, you have missed some opportunities to enhance your code then ;-)
Consider following use cases:
1) Iterating over array property, where and item should be stored in a
temporary variable
to avoid rereated calls to GetItem method inside the loop iteration:
var
i: integer; item: TItem;
...
for i := 0 to obj.ItemCount do begin
item := Items[i];
... item ... item ...
end;

versus

var
item: TItem;
...
for item in obj.Items do begin
... item ... item ...
end;

the latter is safer, simpler and more clear code.

2) Iterating over characters in string -- at first, it seems no
different from any other array,
but consider UTF-8 strings. Using s[i] notation in a loop will lead to
O(n^2) time,
while 'for ... in' can generate linear-time code.

3) Iterating over hash, tree, dataset, or really anything more complex
than an array --
there is currently no language support for that, which leads to many
awkward, buggy and incompatible implementations.

[regarding 'case of string']
Post by Marco van de Voort
Yes. But since this is not a simple type, but a complex type, it goes to a
different class. If that is your argument, make sure it works for arrays, records,
classes, interfaces and the other complex types too.
I definitely agree that 'case' should work for classes --
perhaps even more important than for strings. For records and static arrays
it could be implemented, but the value of such feature would be truly marginal.
For the other types, including class objects and dynamic arrays, 'case'
is useless since equality semantics for them involves reference comparison,
and the references will never be the same.
Post by Marco van de Voort
I don't see string as a scalar type. It is an array or complex type IMHO.
It should be an 'array of char' then.
I agree that the latter would be a better design decision, but it is
too late to change.
--
Alexander S. Klenin
Graeme Geldenhuys
2009-03-26 12:12:26 UTC
Permalink
Post by Alexander Klenin
Post by Marco van de Voort
And I assume that by "lack of iterators" you mean in-language iterators?
Of course. What else?
External iterators without the need for implementing descendants. But
I must agree, it would really be nice if we can incorporate iterators
in all list/container classes.

Would the FPC developers accept such a patch? With unit tests of
coarse. :-) It will not break anything, because it never existed
before - not in Delphi or FPC. But it would make FPC classes a lot
more user friendly.
Post by Alexander Klenin
versus
var
 item: TItem;
...
for item in obj.Items do begin
 ... item ... item ...
end;
the latter is safer, simpler and more clear code.
var
itr: ITBStringIterator;
begin
itr := gIteratorFactory..StringIterator(MyStringList);
while MyStringIterator.HasNext do
writeln(itr.Next); // .Next does not increment the iterator.
...
// do something else with itr.Next
end;
// itr gets free'ed automatically for us...
end;


We can even have filtered iterators using regular expressions. You can
iterate over certain items only be that files in a diretory or strings
in a TStringList etc...

fitr := gIteratorFactory.FilteredStringIterator(MyStringsCollection, 'foob.*r');
while fitr.HasNext do
DoSomethingWithItem(fitr.Next);


Here is an example of the supported iterator API I have implemented.

Function Description
===============================================================
Add(item) Inserts a specified item into the collection.
(optional modifier operation)
HasNext() Returns true if the collection has more items
when traversing the collection in the forward
direction.
HasPrevious() Returns true if the collection has more items
when traversing the collection in the reverse
direction.
Next() Returns the next item in the collection.
Previous() Returns the previous item in the collection.
Reset() Jump to the beginning of the collection, setting
the cursor/index before the first item in the
collection. The iterator is now in the same state
as if you just created it.
ToBack() Jump to the end off the collection, setting
the cursor/index after the last item in the
collection. This needs to be called before you
want to traverse the collection in the reverse
order.
PeekNext() Returns the next item without moving the
iterator's cursor/index.
PeekPrevious() Returns the previous item without moving the
iterator's cursor/index.
Remove() Removes from the collection the last item that
was returned by the Next() or Previous() calls.
(optional modifier operation)
SetItem(item) Replaces the last item returned by the Next()
or Previous() calls with the specified item.
(optional modifier operation)
-------------------------------------


A *huge* benefit of using iterators, is that the developers doesn't
need to worry about if the list/container is 0-based or 1-based, how
to get the next or previous item etc... It now gives the developer a
consistent interface API to work with, no matter what is being
iterated.


Regards,
- Graeme -


_______________________________________________
fpGUI - a cross-platform Free Pascal GUI toolkit
http://opensoft.homeip.net/fpgui/
Dariusz Mazur
2009-03-26 16:06:33 UTC
Permalink
HI
Sorry, this shuld be new topic on pascal devel list, but on other side
this is reply on those post.
Post by Graeme Geldenhuys
Post by Alexander Klenin
Post by Marco van de Voort
And I assume that by "lack of iterators" you mean in-language iterators?
Of course. What else?
External iterators without the need for implementing descendants. But
I must agree, it would really be nice if we can incorporate iterators
in all list/container classes.
Would the FPC developers accept such a patch? With unit tests of
coarse. :-) It will not break anything, because it never existed
before - not in Delphi or FPC. But it would make FPC classes a lot
more user friendly.
Post by Alexander Klenin
versus
var
item: TItem;
...
for item in obj.Items do begin
... item ... item ...
end;
the latter is safer, simpler and more clear code.
var
itr: ITBStringIterator;
begin
itr := gIteratorFactory..StringIterator(MyStringList);
while MyStringIterator.HasNext do
writeln(itr.Next); // .Next does not increment the iterator.
...
// do something else with itr.Next
end;
// itr gets free'ed automatically for us...
end;
Traverse through container (list, array) has many approaches. In pascal
we have 3 loop. Each of them is different.
FOR is fastest, may include initialization: for i:=itr.start to itr.last do
but is impossible to change way of computation in runtime (i think
about change of direction, count )
and is no finalization

REPEAT and WHILE: here is impossible to add default initialization, but
finalization yes. In loop body we can change everything.
thus in my program I use

for i := itr.start to itr.last do

or

if itr.start do repeat
until itr.last;

It was be nice to have in language something like this:

interface
tTest = class
function start:boolean;
function last:boolean;
property iterator begin start stop last;
....
implementation
var
t : tTest
begin
t.iterator do
begin
end;

end;

that will be equivalent to

begin
if t.start then repeat
until t.last.
end;

but then can be test by compiler (if we use both function of pair)
in this construction we can achieve flexible iterator and pattern RAII
(exception handling should be added)
and even invoke function with locking

property locking begin lock stop unlock;

t.locking do something;

Of course when i think that this is valuable, I should prepare path. But
alone cant do this: too much code to understand on beginning.
I need assistance of core developer: where start, what use. I this its
similar to generic parser (I think).
I may start from test cases (of course after discussion about syntax)
--
Darek
Hans-Peter Diettrich
2009-03-27 01:22:17 UTC
Permalink
Post by Graeme Geldenhuys
HasNext() Returns true if the collection has more items
when traversing the collection in the forward
direction.
This (and the Peek methods) require that the collection is organized
strictly sequential, for Previous in both directions. The implementation
for an DataSet can consume an considerable amount of time for such
operations. It looks to me as if such an iterator interface has very
limited practical use.
Post by Graeme Geldenhuys
Remove() Removes from the collection the last item that
was returned by the Next() or Previous() calls.
(optional modifier operation)
SetItem(item) Replaces the last item returned by the Next()
or Previous() calls with the specified item.
(optional modifier operation)
Which element will the iterator represent, after such an operation?
After Remove it has to represent the next or previous item, depending on
the direction of traversion.
Post by Graeme Geldenhuys
A *huge* benefit of using iterators, is that the developers doesn't
need to worry about if the list/container is 0-based or 1-based, how
to get the next or previous item etc... It now gives the developer a
consistent interface API to work with, no matter what is being
iterated.
Nice try, but I prefer the slimmer Count and Item[] interface, with a
chance to remember the index of a found item, and with immediate use of
an item without an type cast. I.e. I never used collections at all, but
that's not an argument against using collections and iterators at all,
only my personal preference ;-)

DoDi
Graeme Geldenhuys
2009-03-27 07:03:48 UTC
Permalink
On Fri, Mar 27, 2009 at 3:22 AM, Hans-Peter Diettrich
Post by Hans-Peter Diettrich
HasNext()         Returns true if the collection has more items
                  when traversing the collection in the forward
                  direction.
This (and the Peek methods) require that the collection is organized
strictly sequential, for Previous in both directions. The implementation
for an DataSet can consume an considerable amount of time for such
operations. It looks to me as if such an iterator interface has very
limited practical use.
I have not used TDataSet or TClientDataset components in years, but
from what I remember they retrieve a few records at a time, it the
source is huge. As for working with my data via tiOPF, my lists are
always fully populated, but with partial objects - the object is in a
posPK state and not a posClean (fully populated) state. So I can
retrieve a lot more records (objects) with a penalty. Objects are then
fully populated as I need them. Also, I don't blindly do a 'select *
from', my GUI interface always has some filter before I retrieve any
data.

As for limited practical use - that is debatable. I find them very
useful. Not to mention every java container/list class has built in
iterator support. It java everything uses iterators!
Post by Hans-Peter Diettrich
Remove()          Removes from the collection the last item that
                  was returned by the Next() or Previous() calls.
                  (optional modifier operation)
SetItem(item)     Replaces the last item returned by the Next()
                  or Previous() calls with the specified item.
                  (optional modifier operation)
Which element will the iterator represent, after such an operation?
After Remove it has to represent the next or previous item, depending on
the direction of traversion.
Which is handled very easily - my article explains this clearly. Each
iterator has a FCursor private field that tracks the cursor position.
My iterators are implement as in the Java-style iterators, which means
they point between elements and not at elements. Hence the reason I
don't have a iterator.Current(..) API call. This makes implementing
modifier methods like Remove() much easier as well. If you want, I can
send you my article and code which should explain all this and more
much clearer.
Post by Hans-Peter Diettrich
Nice try, but I prefer the slimmer Count and Item[] interface, with a
chance to remember the index of a found item, and with immediate use of
an item without an type cast.
Excuse me, but I don't have a single type cast in my code either. Have
you actually tried iterators before? Not having to worry about how to
access the list element, if the list is 0 or 1 based, no counter
variable etc are all huge bonuses for me. Plus I can switch internal
list/container classes in my business objects with minimal code
changes to my iterators. I just need to change the iterator type,
simply because the iterator interface does not change, no matter what
list/container class I am iterating. So the way of accessing the
elements in a list never changes.
Post by Hans-Peter Diettrich
that's not an argument against using collections and iterators at all,
only my personal preference ;-)
That's your choice then, but you don't know what you are missing. ;-)


Regards,
- Graeme -


_______________________________________________
fpGUI - a cross-platform Free Pascal GUI toolkit
http://opensoft.homeip.net/fpgui/
Alexander Klenin
2009-03-27 08:26:19 UTC
Permalink
On Fri, Mar 27, 2009 at 11:22, Hans-Peter Diettrich
<***@aol.com> wrote:

[critique of Graeme's iterators]

Since Graeme did not wish to post his article in the open, perhaps he
also did not wish it to be cited?
Anyway, I understood his design from the quote and agree with some of
your critique.

Please see the code I send to the list for my take on iterators.
Note that it is only a proof-of-concept, without complete set of methods.
--
Alexander S. Klenin
Graeme Geldenhuys
2009-03-27 08:49:35 UTC
Permalink
Post by Alexander Klenin
Since Graeme did not wish to post his article in the open, perhaps he
also did not wish it to be cited?
The article was written for a magazine so I do not have the rights to
publicly publish it myself. I you want to read it, buy the Toolbox
magazine (German translation) and back-order Toolbox 1'2009 or ask and
I will email you in private the original English version.
Post by Alexander Klenin
Anyway, I understood his design from the quote and agree with some of
your critique.
The article explains is much better than the code snippets I posted in
this mailing list.


Regards,
- Graeme -


_______________________________________________
fpGUI - a cross-platform Free Pascal GUI toolkit
http://opensoft.homeip.net/fpgui/
Alexander Klenin
2009-03-27 08:59:13 UTC
Permalink
On Fri, Mar 27, 2009 at 18:49, Graeme Geldenhuys
Post by Graeme Geldenhuys
The article was written for a magazine so I do not have the rights to
publicly publish it myself.  I you want to read it, buy the Toolbox
magazine (German translation) and back-order Toolbox 1'2009 or ask and
I will email you in private the original English version.
It is not that, I just wanted to note that citing it might be also
forbidden/illegal,
sorry for being unclear.
--
Alexander S. Klenin
Graeme Geldenhuys
2009-03-27 09:24:14 UTC
Permalink
Post by Alexander Klenin
It is not that, I just wanted to note that citing it might be also
forbidden/illegal, sorry for being unclear.
Ah ok. :) I've been meaning to email the editor to ask permission for
articles that has been in print some months ago. I'll do so now.


Regards,
- Graeme -


_______________________________________________
fpGUI - a cross-platform Free Pascal GUI toolkit
http://opensoft.homeip.net/fpgui/
Graeme Geldenhuys
2009-03-27 13:08:11 UTC
Permalink
Post by Alexander Klenin
Post by Graeme Geldenhuys
The article was written for a magazine so I do not have the rights to
publicly publish it myself.  I you want to read it, buy the Toolbox
magazine (German translation) and back-order Toolbox 1'2009 or ask and
I will email you in private the original English version.
It is not that, I just wanted to note that citing it might be also
forbidden/illegal, sorry for being unclear.
OK, I got permission from my editor to publish older articles. I'll
add more as permitted.

http://opensoft.homeip.net/articles/


Regards,
- Graeme -


_______________________________________________
fpGUI - a cross-platform Free Pascal GUI toolkit
http://opensoft.homeip.net/fpgui/
Marco van de Voort
2009-03-28 20:04:41 UTC
Permalink
Post by Hans-Peter Diettrich
Post by Graeme Geldenhuys
HasNext() Returns true if the collection has more items
when traversing the collection in the forward
direction.
This (and the Peek methods) require that the collection is organized
strictly sequential, for Previous in both directions.
Not really. It only says that you need either a way to determine if there
are more elements or one element lookahead.

I have my doubts about previous being part of the base iterator though.
That is as limiting as a "everything is a vector" approach to iterators.

Just "eof" and "next" should be it. If you want to go backwards, see if the
collection provides a separate iterator for the backwards motion. But having
it in the base spec means that it is defunct half of the time, and, like
vector is a too complicated abstraciton for an iteration.
Post by Hans-Peter Diettrich
The implementation for an DataSet can consume an considerable amount of
time for such operations. It looks to me as if such an iterator interface
has very limited practical use.
Why is would this slower than a vector <count/items> type of iterator?
Because one can implement a real iterator on top of a vector
(hasnext:=(currentrec<count))
Post by Hans-Peter Diettrich
Post by Graeme Geldenhuys
Remove() Removes from the collection the last item that
was returned by the Next() or Previous() calls.
(optional modifier operation)
SetItem(item) Replaces the last item returned by the Next()
or Previous() calls with the specified item.
(optional modifier operation)
Which element will the iterator represent, after such an operation?
The first not seen element or end-of-iteration.
Post by Hans-Peter Diettrich
After Remove it has to represent the next or previous item, depending on
the direction of traversion.
Post by Graeme Geldenhuys
A *huge* benefit of using iterators, is that the developers doesn't
need to worry about if the list/container is 0-based or 1-based, how
to get the next or previous item etc... It now gives the developer a
consistent interface API to work with, no matter what is being
iterated.
Nice try, but I prefer the slimmer Count and Item[] interface,
Problem is that that requires to know the count up front, AND you can't nest
it in the way you can streams.

(have an iterator B that iterates with iterator A over a collection, but skip some)
Marco van de Voort
2009-03-26 12:21:44 UTC
Permalink
Post by Alexander Klenin
Post by Marco van de Voort
Post by Alexander Klenin
Lack of iterators.
No it doesn't IMHO.
This is really nice argument ;-) Well, it _should_ solve it.
If it does not, it must be extended of implemented differently.
I definitely do not argue in favor of blindly copying Delphi features.
Post by Marco van de Voort
And I assume that by "lack of iterators" you mean in-language iterators?
Of course. What else?
Well, first must be determined if in-language iterator is mandatory, or if
runtime approaches (like afaik Java) also work.
Post by Alexander Klenin
Post by Marco van de Voort
One can give this "handy" moniker to every randomly thought up with an
example that shortens some random code fragment. IMHO it is meaningless.
As I said, I agree that the case for 'strict' visibility is rather weak.
However, it still has practical uses. For a recent example: Lazarus contains
some extremely overbloated source files, some more than 10000 lines long,
with dozens of classes.
The task of refactoring them into a reasonable set of units is daunting.
It would be made easier if I were able to first isolate classes inside the unit
with 'strict' visibility specifiers to make sure nothing breaks
when I move those classes away.
That is abuse, not use. Refactoring by trial and error, better promote the
efforts towards a good language analyser.
Post by Alexander Klenin
Post by Marco van de Voort
I'm also not entirely happy with the way dynamic arrays are set up. They
seem to be made mostly for COM use, the mandatory 0-basedness is unpascal
like etc.
The real problem of dynamic arrays is O(n^2) growing time.
Is they, like TList, contained separate 'Length" and 'Capacity'
fields, they would be
much more useful -- to the point that TList could be totally superseded.
Tlist is untyped. But generics will change this a lot.

I think about the only strength of dyn array is exactly their simplicity.
Not everything and the kitchen sink, just a common pattern for daily use.

One can try to insert lots of extra patterns (like your growth part), but
there are so many ways to go with that (do you keep it indexed? Do you keep
it linearly in memory ?) etc. Also some of these extra patterns would
potentially break essential features used now (namely that the elements are
lineairly in memory allows to pass the address to a C subroutine)
Post by Alexander Klenin
Post by Marco van de Voort
I can live with such an argumentation. However, if I take the case of
string as example, I see only very rare occasions, and I wouldn't even
use case of string because it is so limited. If suddenly the cases
wouldn't be compiletime anymore (because they become user configurable
or localised values) you have to morph the entire block.
If they are not constants, the user should use 'if', this is obvious.
I'm only saying that I usually wouldn't even use case-string if there were
even a chance on non constants.
Post by Alexander Klenin
And of course cases should not be localised.
And that is odd. Nearly every constant string nowdays is localised sooner or
later.
Post by Alexander Klenin
I am talking about such use cases as tokenizers and protocol handlers.
I know. But nearly all nontrivial ones won't use it also, because of speed
reasons, exceptions to general rules that need to be handled etc.

The application field of this feature is so horribly small.
Post by Alexander Klenin
Post by Marco van de Voort
They copied it from languages that have class as the only namespace. However
the unit based Pascal concept already has units and the unit namespace to
identify between similarly global symbols.
When the codebase becomes big enough, more than one level of hierarchy
becomes useful.
Nicely said. Care to explain how this actually works in practice? You can't
pass a general namespace reference around.
Post by Alexander Klenin
Post by Marco van de Voort
Post by Alexander Klenin
Like for ... in?
I never used in under Delphi except to iterate over sets.
Well, you have missed some opportunities to enhance your code then ;-)
1) Iterating over array property, where and item should be stored in a
temporary variable
var
i: integer; item: TItem;
...
for i := 0 to obj.ItemCount do begin
item := Items[i];
... item ... item ...
end;
Minus one btw.
Post by Alexander Klenin
versus
var
item: TItem;
...
for item in obj.Items do begin
... item ... item ...
end;
the latter is safer, simpler and more clear code.
No, since for all common usage patterns based the IDE codetools creates the
pattern for you.
Post by Alexander Klenin
2) Iterating over characters in string -- at first, it seems no
different from any other array,
but consider UTF-8 strings. Using s[i] notation in a loop will lead to
O(n^2) time,
while 'for ... in' can generate linear-time code.
Only with a lot of more extensions. Since currently there is not even a
utf-8 string concept or char.
Post by Alexander Klenin
3) Iterating over hash, tree, dataset, or really anything more complex
than an array --
there is currently no language support for that, which leads to many
awkward, buggy and incompatible implementations.
I still don't see it.
Post by Alexander Klenin
[regarding 'case of string']
Post by Marco van de Voort
Yes. But since this is not a simple type, but a complex type, it goes to a
different class. If that is your argument, make sure it works for arrays, records,
classes, interfaces and the other complex types too.
I definitely agree that 'case' should work for classes --
perhaps even more important than for strings.
So there goes the orthogonality of arguments being compiletime. I assume you
want to use ducktyping too? It seems the trend nowadays.
Post by Alexander Klenin
For records and static arrays
it could be implemented, but the value of such feature would be truly marginal.
For the other types, including class objects and dynamic arrays, 'case'
is useless since equality semantics for them involves reference comparison,
and the references will never be the same.
Useless baroque extensions made "because we can", not because it serves a
purpose IMHO. Such experiments belong in experimental languages, not
something that strives to be usable for production use.
Post by Alexander Klenin
Post by Marco van de Voort
I don't see string as a scalar type. It is an array or complex type IMHO.
It should be an 'array of char' then.
I agree that the latter would be a better design decision, but it is
too late to change.
What do you do with the other 18 string variants beside "string" and array[0..x] of
char (and which one do you mean exactly ? The dynamic, the static the open
array kind or the literal kind? Maybe some of these coalesce, but there are
more than one)

(a short summary at

http://www.stack.nl/~marcov/delphistringtypes.txt

don't forget to define all these cases (and expressions between them) for
the <case of string> patch :-)

note that the above link doesn't yet include D2009 stringtypes (and some of
them are in 2.3.1).
Graeme Geldenhuys
2009-03-26 12:41:13 UTC
Permalink
Post by Marco van de Voort
var
  i: integer; item: TItem;
...
for i := 0 to obj.ItemCount do begin
  item := Items[i];
  ... item ... item ...
end;
Minus one btw.
And my iterator case is proven. :-) Like I said earlier - one of the
reasons I implemented iterators for all list/container classes I use.
No need to remember -1 in the if... line or the 0-based vs 1-based
etc...

Regards,
- Graeme -


_______________________________________________
fpGUI - a cross-platform Free Pascal GUI toolkit
http://opensoft.homeip.net/fpgui/
Marco van de Voort
2009-03-26 20:37:24 UTC
Permalink
Post by Graeme Geldenhuys
Post by Marco van de Voort
?? i: integer; item: TItem;
...
for i := 0 to obj.ItemCount do begin
?? item := Items[i];
?? ... item ... item ...
end;
Minus one btw.
And my iterator case is proven. :-) Like I said earlier - one of the
reasons I implemented iterators for all list/container classes I use.
No need to remember -1 in the if... line or the 0-based vs 1-based
etc...
You snipped this:

No, since for all common usage patterns based the IDE codetools creates the
pattern for you.
Marc Weustink
2009-03-26 13:07:40 UTC
Permalink
Post by Alexander Klenin
1) Iterating over array property, where and item should be stored in a
temporary variable
var
i: integer; item: TItem;
...
for i := 0 to obj.ItemCount do begin
item := Items[i];
... item ... item ...
end;
versus
var
item: TItem;
...
for item in obj.Items do begin
... item ... item ...
end;
the latter is safer, simpler and more clear code.
ehm, what if I want it reversed ?

and how should the compiler know that there are Count items ?

Marc
Alexander Klenin
2009-03-26 13:33:31 UTC
Permalink
Post by Marc Weustink
Post by Alexander Klenin
1) Iterating over array property, where and item should be stored in a
  temporary variable
var
  i: integer; item: TItem;
...
for i := 0 to obj.ItemCount do begin
  item := Items[i];
  ... item ... item ...
end;
versus
var
  item: TItem;
...
for item in obj.Items do begin
  ... item ... item ...
end;
the latter is safer, simpler and more clear code.
ehm, what if I want it reversed ?
Reverse iteration might be common enough to warrant a special syntax,
but in general all non-standard iteration orders should fall back to indexing.
Post by Marc Weustink
and how should the compiler know that there are Count items ?
It should not. Iterators are usually based on end-of-items condition,
not counting (since the latter might be unavailabe or inefficient for
some containers).
--
Alexander S. Klenin
Graeme Geldenhuys
2009-03-26 13:47:23 UTC
Permalink
Post by Alexander Klenin
Post by Marc Weustink
Post by Alexander Klenin
...
for item in obj.Items do begin
  ... item ... item ...
end;
the latter is safer, simpler and more clear code.
ehm, what if I want it reversed ?
Reverse iteration might be common enough to warrant a special syntax,
but in general all non-standard iteration orders should fall back to indexing.
That sucks. :-( In that case, I'll stick to my home-grown iterators
which gives me a consistent interfaces no matter the
list/container/component class or the direction I want to iterate.


Regards,
- Graeme -


_______________________________________________
fpGUI - a cross-platform Free Pascal GUI toolkit
http://opensoft.homeip.net/fpgui/
Paul Ishenin
2009-03-26 14:22:40 UTC
Permalink
Post by Alexander Klenin
Reverse iteration might be common enough to warrant a special syntax,
but in general all non-standard iteration orders should fall back to indexing.
Then better to extend sintax:

using default iterator = delphi compatible

FOR s IN list DO
WriteLn(s);

extended:

FOR s IN list USING my_reverse_iterator DO
WriteLn(s);

In upper case I wrote keywords and in lower case identifiers.

Best regards,
Paul Ishenin.
Alexander Klenin
2009-03-26 15:10:40 UTC
Permalink
Post by Paul Ishenin
FOR s IN list DO
 WriteLn(s);
FOR s IN list USING my_reverse_iterator DO
 WriteLn(s);
In upper case I wrote keywords and in lower case identifiers.
I think the extension can be avoided like so:

FOR s IN reverse(list) DO

where reverse is a standard (or user-defined) function returning iterator.

FOR s IN list DO

will be a syntax sugar for

FOR s IN default_iterator(list) DO

where default_iterator is defined for built-in containers and can be
redefined for
user-defined ones.

This can _almost_ be emulated at the library level -- look at the
attached example.

However, few problems exist:
1) overloading of operator := was designed without thinking, it should
be a procedure
with 'var' parameter instead of a function, because assignment often
requires access
to a previous state of l-value. So, rather ugly 'property V' is required.
2) 'while ForEach(a, r) do' is IMO less clear syntax than 'for a in r do'
3) user have to declare 'a: TIntegerArrayIterator' instead of simply
'a: Integer'
4) Note that I overloaded operator + only.
In practice, all relevant operators should be overloaded, which is bulky.
5) Finally, all this code have to be written for every
container/element combination.
Generics might or might not help here -- but at this stage built-in
implementation
would actually be simpler then library-based one.
--
Alexander S. Klenin
Hans-Peter Diettrich
2009-03-27 00:51:52 UTC
Permalink
Post by Alexander Klenin
2) Iterating over characters in string -- at first, it seems no
different from any other array,
but consider UTF-8 strings. Using s[i] notation in a loop will lead to
O(n^2) time,
while 'for ... in' can generate linear-time code.
Please note that for an iteration over UTF-8 strings the data type
'string' is required, to hold the equivalent of a multi-byte UTF
"character". Unless there exist data types for both UTF8String and
UTF8Char, or MBCSString and MBCSChar etc., a 'for ... in' construct is
rather useless.
Post by Alexander Klenin
3) Iterating over hash, tree, dataset, or really anything more complex
than an array --
there is currently no language support for that, which leads to many
awkward, buggy and incompatible implementations.
IMO the same as for strings. As is, the compiler can only handle basic
types, where e.g. a string is an array of fixed size elements (Char,
WideChar), with consequently a fixed length. Everything else can be
supported only by according class methods or user-supplied operators,
which again open the chance for different operators in different units,
projects, libraries...
Post by Alexander Klenin
[regarding 'case of string']
Post by Marco van de Voort
Yes. But since this is not a simple type, but a complex type, it goes to a
different class. If that is your argument, make sure it works for arrays, records,
classes, interfaces and the other complex types too.
I definitely agree that 'case' should work for classes --
perhaps even more important than for strings. For records and static arrays
it could be implemented, but the value of such feature would be truly marginal.
How would you define the equality and ranges of such types? I.e. what's
the literal value and representation of the case label for an record?
What for 'RecA..RecX:'?

DoDi
Martin Friebe
2009-03-26 11:06:03 UTC
Permalink
Post by Marco van de Voort
Post by Alexander Klenin
Since string was introduced as built-in "scalar" type with defined
equality, lack of 'case' support can be viewed as a design bug.
I don't see string as a scalar type. It is an array or complex type IMHO.
True,...

anyway, best argument(s) I think I saw for string case so far:

1) Readability.
I think it is true, 10 or more lines of IF...ELSE IF ... can obscure
readability.

I wonder how many of the cases where this happens, actually are truly
needed?
How many of them could have used a simpler data-type, and how many of
them would have wanted are more specialized approach such as LEX?


2) Optimizations:
If string-case existed, the compiler could optimize the code, by using
hashes or tree like lookup.

While that's true, I wonder if that is really a good idea. It would be
the first step of embedding LEX/YACC into the language.
One may say this is of benefits for beginners, because the need to learn
less about other tools; the truth is, discouraging a beginner from
learning has no long time benefit.

I think if you have large enough string casings and need the speed, you
sghould use the tools specially made for this.


Just some thoughts from me / Regards
Martin
Reenen Laurie
2009-03-26 11:32:54 UTC
Permalink
Getting back to the original question...

I implemented it with (as Michael van Canneyt suggested)

function wcase(Needle:string;Haystack:array of string):integer;
begin
Result:=High(HayStack);
While (Result>=0) and (CompareText(Needle,Haystack[Result])<>0) do
Dec(Result);
end;

case wcase(s,['network command 1','network command 2','network command
3','network command 4']) of
{'network command 1'} 0 :
{'network command 2'} 1 :
{'network command 3'} 2 :
{'network command 4'} 3 :
end;

It's decent on readability, but not at all great in maintainability. If I
want to add network command 1.5 (let's say it makes sense to put it there,
because it does something similar to 1 and 2)... then I need to put it in
the array (which if there is 50 network commands can be a LOT), then I need
to add it the case statement.

Obviously in my case, making all my network commands an ordinal type, and
sending the ordinal value through would make the program more efficient etc.
But it's my first networking app, and I want it easy to debug, and human
readable when it comes through the pipe...

I guess usually when one would want to have a string case, it's probably bad
programming in terms of efficiency... and one should rather encourage good
programming practices than optimize bad programming practices with hash
tables/tree lookups.

Regards,
-Reenen
Marco van de Voort
2009-03-26 12:29:24 UTC
Permalink
Post by Martin Friebe
Post by Marco van de Voort
Post by Alexander Klenin
Since string was introduced as built-in "scalar" type with defined
equality, lack of 'case' support can be viewed as a design bug.
I don't see string as a scalar type. It is an array or complex type IMHO.
1) Readability.
I think it is true, 10 or more lines of IF...ELSE IF ... can obscure
readability.
I wonder how many of the cases where this happens, actually are truly
needed?
How many of them could have used a simpler data-type, and how many of
them would have wanted are more specialized approach such as LEX?
Exactly. Also the alternative presented wasn't if then nesting, but rather a
library routine that is like a POS for array of string.
Post by Martin Friebe
If string-case existed, the compiler could optimize the code, by using
hashes or tree like lookup.
This can be done better by the library procedure, since that is more easily
changable than language. Including hash algorithm etc.
Post by Martin Friebe
While that's true, I wonder if that is really a good idea. It would be
the first step of embedding LEX/YACC into the language.
One may say this is of benefits for beginners, because the need to learn
less about other tools; the truth is, discouraging a beginner from
learning has no long time benefit.
I doubt this is so good for the beginner. Nearly no tokenizer works this
way.
Post by Martin Friebe
I think if you have large enough string casings and need the speed, you
sghould use the tools specially made for this.
If the need was really this high, probably lazarus already would have a
lexer/yacc like app internal, and you could edit grammars in a comfortable
editor, with diagramming and consistency checking support.

It is so horrible little subset of a parser, it is next to useless, except
for the last poor guy coming from basic that wants to "streamline/modernize" his
nested if..then's without really thinking about the problem.
Graeme Geldenhuys
2009-03-26 11:50:56 UTC
Permalink
Post by Marco van de Voort
Post by Alexander Klenin
Post by Marco van de Voort
What problem does "for in" really solve?
Lack of iterators.
No it doesn't IMHO. And I assume that by "lack of iterators" you mean
in-language iterators?
Iterators are quite doable with all the base list/container classes. I
wrote a few months ago an article for Toolbox magazine where I
explained how to created such iterators for all list/container classes
and without the need to create descendant classes. I have been using
such iterators for years!

If anybody would like to read the article or see the code, it is on a
request basis - I may not publicly publish the article.

Regards,
- Graeme -


_______________________________________________
fpGUI - a cross-platform Free Pascal GUI toolkit
http://opensoft.homeip.net/fpgui/
Marco van de Voort
2009-03-26 12:32:10 UTC
Permalink
Post by Graeme Geldenhuys
Post by Marco van de Voort
Post by Alexander Klenin
Lack of iterators.
No it doesn't IMHO. And I assume that by "lack of iterators" you mean
in-language iterators?
Iterators are quite doable with all the base list/container classes. I
wrote a few months ago an article for Toolbox magazine where I
explained how to created such iterators for all list/container classes
and without the need to create descendant classes. I have been using
such iterators for years!
Well, I ported decal, and have a special case in lightcontainers. , and both
have library iterators too (not that I advise either of these pkgs, as they
are both specialties, but as examples they are ok ).
Post by Graeme Geldenhuys
If anybody would like to read the article or see the code, it is on a
request basis - I may not publicly publish the article.
I would like to yes. Containertypes is one of my interests.
Lord Satan
2009-03-26 20:35:50 UTC
Permalink
On Thu, 26 Mar 2009 13:32:10 +0100
Post by Marco van de Voort
Post by Graeme Geldenhuys
If anybody would like to read the article or see the code, it is on a
request basis - I may not publicly publish the article.
I would like to yes. Containertypes is one of my interests.
I am interested, too. It would be very nice of you, Graeme, to send me the article and the code.

tia
--
A: Because it messes up the order in which people normally read text.
Q: Why is top-posting such a bad thing?
A: Top-posting.
Q: What is the most annoying thing in e-mail?
Paul Nicholls
2009-03-27 00:23:43 UTC
Permalink
----- Original Message -----
From: "Graeme Geldenhuys" <***@gmail.com>
Newsgroups: gmane.comp.ide.lazarus.general
To: "General mailing list" <***@lazarus.freepascal.org>
Sent: Thursday, March 26, 2009 10:50 PM
Subject: Re: Easiest way to "case" strings
Post by Graeme Geldenhuys
Post by Marco van de Voort
Post by Alexander Klenin
Post by Marco van de Voort
What problem does "for in" really solve?
Lack of iterators.
No it doesn't IMHO. And I assume that by "lack of iterators" you mean
in-language iterators?
Iterators are quite doable with all the base list/container classes. I
wrote a few months ago an article for Toolbox magazine where I
explained how to created such iterators for all list/container classes
and without the need to create descendant classes. I have been using
such iterators for years!
If anybody would like to read the article or see the code, it is on a
request basis - I may not publicly publish the article.
Regards,
- Graeme -
Hi Graeme, I would also be interested your article (and code)...it sounds
very interesting :-)

paulfnicholls AT gmail DOT com

cheers,
Paul
Sayyid Ibnu Husein Alatas
2009-03-27 07:16:54 UTC
Permalink
________________________________
From: "Graeme Geldenhuys" <***@gmail.com>
Sent: Friday, March 27, 2009 7:23:43 AM
Subject: Re: [Lazarus] Easiest way to "case" strings
... ...
Iterators are quite doable with all the base list/container classes. I
wrote a few months ago an article for Toolbox magazine where I
explained how to created such iterators for all list/container classes
and without the need to create descendant classes. I have been using
such iterators for years!
If anybody would like to read the article or see the code, it is on a
request basis - I may not publicly publish the article.
Regards,
- Graeme -
_______________________________________________

Hi Graeme, that's seem an interesting article (and code, of course), and just like Paul, I would also be delightful to read your article (and code). :-)

ibnuhusein2000 at yahoo dot com
Florian Klaempfl
2009-03-26 09:00:00 UTC
Permalink
Post by Alexander Klenin
Post by Marco van de Voort
Since we are close to 20 stringtypes + conversions now, I doubt that this is
really the problem.
Yes, I agree that the string types in FPC are a mess,
and judging by recent discussion, they are planned to became worse.
This happens if every string type someone could imagine is implemented ;)
Post by Alexander Klenin
Post by Marco van de Voort
Is having 6 levels of information
hiding (private,public,strict protected, strict private,protected,published)
or are the strict* ones just to stop the whining of people that come from
other languages?
No, it is not necessary, but handy sometimes. I agree that these are
not a big deal,
and FPC can live without them quite fine, but they do not break anything either.
The problem is: every language needs testing and maintainance. And even
simple language features can have interferences with other code nobody
might see at a first glance.

Anyways, as I said, new language features are ok if they come as a
proper patch with tests and docs.
Richard Ward
2009-03-26 16:02:22 UTC
Permalink
Post by Marco van de Voort
No, since for all common usage patterns based the IDE codetools
creates the
pattern for you.
-----

I don't currently use an IDE which performs these types of things.
I've just peeked at the Lazarus IDE (Macintosh implementation) for the
first time a couple weeks ago. I assume we are talking about the Laz
IDE? Even if implemented in _all_ IDE's, it would be nice (albeit
arguably not _needed_) to be in the language.
Loading...