Sign in Join

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

Mailing lists / lazarus / 2009-03

Easiest way to "case" strings

70 messages · 19 people · –

Reply by email Subscribe to this list Your subscription

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

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...

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. -------------- next part -------------- An HTML attachment was scrubbed... URL: http://www.lazarus.freepascal.org/pipermail/lazarus/attachments/20090321/80dbdc5d/attachment.html

Reply by email

Michael Van Canneyt
to Reenen Laurie
Reenen Laurie wrote 37 lines
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"?

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.

Reply by email

Vincent Snijders
to Reenen Laurie: I'm sure most of you have had this... is there an easy way to have a case statement…
Reenen Laurie wrote 6 lines
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

Reply by email

Alexander Klenin
to Vincent Snijders
Vincent Snijders wrote 13 lines
Reenen Laurie schreef: > 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.

Hm, this function duplicates AnsiIndexStr / AnsiIndexText which are Delphi-compatible. Is there a reason for its existence?

Alexander S. Klenin

Reply by email

Marc Weustink
to Alexander Klenin
Alexander Klenin wrote 17 lines
On Sat, Mar 21, 2009 at 20:03, Vincent Snijders wrote: > Reenen Laurie schreef: >> 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. 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

Reply by email

Alexander Klenin
to Marc Weustink
Marc Weustink wrote 5 lines
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

Reply by email

Lee Jenkins
to Vincent Snijders: You can use stringcase: http://lazarus-ccr.sourceforge.net/docs/lcl/lclproc/stringcase.htm…
Vincent Snijders wrote 15 lines
Reenen Laurie schreef: > 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

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

Reply by email

Marc Weustink
to Alexander Klenin: They definitely exist in Delphi 7. Google search suggests they were introduced around…
Alexander Klenin wrote 9 lines
On Sat, Mar 21, 2009 at 23:37, Marc Weustink wrote: > 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

Reply by email

Michael Van Canneyt
to Lee Jenkins: Can anyone say why there is no string case statement in Object Pascal? I've always…
Lee Jenkins wrote 23 lines
Vincent Snijders wrote: > Reenen Laurie schreef: >> 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 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.

Reply by email

Alexander Klenin
to Lee Jenkins: Can anyone say why there is no string case statement in Object Pascal? I've always…
Lee Jenkins wrote
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

Reply by email

Flávio Etrusco
to Michael Van Canneyt: In the case of strings, it would mostly be code readability. For ordinal types, a case…
Show quoted text 12 lines
> > 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

Reply by email

Michael Van Canneyt
to Flávio Etrusco
Fl?vio Etrusco wrote 14 lines
>> >> 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.

Reply by email

Reenen Laurie
to Michael Van Canneyt

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.

2009/3/21 Michael Van Canneyt

Show quoted text 39 lines
On Sat, 21 Mar 2009, Fl?vio Etrusco wrote: > >> > >> 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. _______________________________________________ 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. -------------- next part -------------- An HTML attachment was scrubbed... URL: http://www.lazarus.freepascal.org/pipermail/lazarus/attachments/20090321/669fb14e/attachment-0001.html

Reply by email

Alexander Klenin
to Michael Van Canneyt: Even so, there are some serious issues with a string 'case' as a language construct: -…

2009/3/22 Michael Van Canneyt :

Even so, there are some serious issues with a string 'case' as a language construct: - What about encodings ?

Nothing about them, just compare byte-by-byte, as usual string comparison do.

- Should it be case sensitive or not ?

Of course no.

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

Reply by email

Hans-Peter Diettrich
to Alexander Klenin: I'd say it is because nobody contributed it ;-) Both. It can be implemented as prefix…
Show quoted text 5 lines
> 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

Reply by email

Hans-Peter Diettrich
to Alexander Klenin: 2009/3/22 Michael Van Canneyt : Nothing about them, just compare byte-by-byte, as usual…
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

Reply by email

Howard Page-Clark
to Marc Weustink: That might explain, the first incarnation of StringCase was written in D4 Marc
Show quoted text 14 lines
Alexander Klenin wrote: > On Sat, Mar 21, 2009 at 23:37, Marc Weustink > wrote: >> 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

Reply by email

Alexander Klenin
to Hans-Peter Diettrich: There exist too many options with string comparison. In a table lookup the compare method…
Hans-Peter Diettrich wrote
Alexander Klenin schrieb: 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 ;-)

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?

but further extensions should be added very carefully,

Yes, but still they should be added -- that was my point.

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

Reply by email

Alexander Klenin
to Howard Page-Clark: On Sat, 21 Mar 2009 15:39:23 +0100 IndexStr() and AnsiIndexStr() were introduced in the…
Howard Page-Clark wrote
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

Reply by email

Hans-Peter Diettrich
to Alexander Klenin: On Sun, Mar 22, 2009 at 05:36, Hans-Peter Diettrich There are also many ways to implement…
Show quoted text 7 lines
> 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).

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.

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

Reply by email

Howard Page-Clark
to Alexander Klenin: Are you sure? I did not found Delphi 5 installation, but managed to install Delphi 6 --…
Show quoted text 15 lines
On Sun, Mar 22, 2009 at 08:57, Howard Page-Clark wrote: > 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

Reply by email

Alexander Klenin
to Hans-Peter Diettrich: Delphi 2 (or 3?) was the last version with a grammar for the language. After that version…
Hans-Peter Diettrich wrote
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.

> 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 ;-)

Show quoted text 7 lines
> 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

Reply by email

Hans-Peter Diettrich
to Alexander Klenin
> 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).

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 :-(

>> 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.

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

Reply by email

Marco van de Voort
to Alexander Klenin: 2009/3/22 Michael Van Canneyt : Nothing about them, just compare byte-by-byte, as usual…
Alexander Klenin wrote 8 lines
Of course no. > 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.

Reply by email

Alexander Klenin
to Marco van de Voort
Marco van de Voort wrote
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 is what I am ranting about, excessive conservatism leading to a stagnation.

And everytime the same references to other interpreted languages that do such things.

Eh, "other interpreted"? Pascal is compiled, as you surely know.

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

Reply by email

Florian Klaempfl
to Alexander Klenin
Show quoted text 8 lines
On Tue, Mar 24, 2009 at 07:03, Marco van de Voort wrote: > 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.

Reply by email

Alexander Klenin
to Florian Klaempfl
Florian Klaempfl wrote 6 lines
Alexander Klenin schrieb: 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

Reply by email

Florian Klaempfl
to Alexander Klenin
Show quoted text 10 lines
On Tue, Mar 24, 2009 at 22:40, Florian Klaempfl wrote: > Alexander Klenin schrieb: > 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 ;)

Reply by email

Marco van de Voort
to Alexander Klenin: On Sun, Mar 22, 2009 at 05:36, Hans-Peter Diettrich There are also many ways to implement…
Alexander Klenin wrote 8 lines
> Alexander Klenin schrieb: > 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.

Since we are close to 20 stringtypes + conversions now, I doubt that this is really the problem.

This "consider all roads then choose none" approach will, obviously, never allow you to get anywhere ;-)

No. It is just to chose the ones that matter, not the ones that are merely possible.

Show quoted text 7 lines
> 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?

What problem does "for in" really solve?

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?

What is the function of being able to add methods to records?

What is the real use of duplicating const type and var as nested variants inside classes?

Have a look at:
http://www.stack.nl/~marcov/delphilater.txt

> but further extensions should be added very carefully, Yes, but still they should be added -- that was my point.

The old rule used to be that
- it should make something possible that is not doable otherwise.
- _or_ it should be a construct that is used so much that timesavings are noticable

And string-case for my feeling belongs in neither. It is just about racking up bullet lists in language wars.

But apparantly that has been simplified to 'everybody that submits a patch'.

Show quoted text 6 lines
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 ;-)

Judge the extensions to the above.

In my opinion too many people focus way too much on the language, and too little on solving the problem: doing safe programming in a sane amount of time (*). A language is about more than just weighing the language manual.

(*) different tradeoffs safe/time are possible.

Reply by email

Alexander Klenin
to Marco van de Voort
Marco van de Voort wrote
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.

What problem does "for in" really solve?

Lack of iterators.

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.

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.

What is the real use of duplicating const type and var as nested variants inside classes?

Namespace management.

Thanks, that is interesting discussion. I will post my thoughts on that in a separate mail.

The old rule used to be that - it should make something possible that is not doable otherwise.

Like strict private/protected?

- _or_ it should be a construct that is used so much that timesavings are ?noticable

Like for ... in?

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

Reply by email

Flávio Etrusco
to Alexander Klenin
> 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.

Show quoted text 8 lines
> 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.

Show quoted text 6 lines
> 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

Reply by email

Hans-Peter Diettrich
to Flávio Etrusco: Also, Pascal is all about readability and maintainability, so avoiding a redundant…
Show quoted text 8 lines
>> 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

Reply by email

Marco van de Voort
to Alexander Klenin: Yes, I agree that the string types in FPC are a mess, and judging by recent discussion,…
Alexander Klenin wrote
> 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?

Show quoted text 6 lines
> 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.

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

Show quoted text 5 lines
> 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)

> 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.

Show quoted text 5 lines
> Have a look at: > 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

> 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.

> - _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.

Show quoted text 6 lines
> 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.

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.

Reply by email

Florian Klaempfl
to Alexander Klenin: Yes, I agree that the string types in FPC are a mess, and judging by recent discussion,…
Show quoted text 6 lines
On Thu, Mar 26, 2009 at 00:23, Marco van de Voort wrote: > 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 ;)

Show quoted text 9 lines
> 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.

Reply by email

Florian Klaempfl
to Marco van de Voort: No it doesn't IMHO. And I assume that by "lack of iterators" you mean in-language…
Show quoted text 9 lines
>> 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 ;)

Reply by email

Alexander Klenin
to Hans-Peter Diettrich: IMO strings are similarly "scalar" as are floating point numbers, with regards to 'case'.…
Hans-Peter Diettrich wrote 7 lines
Alexander Klenin schrieb: > 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

Reply by email

Alexander Klenin
to Marco van de Voort: No it doesn't IMHO. And I assume that by "lack of iterators" you mean in-language…
Marco van de Voort wrote 6 lines
On Thu, Mar 26, 2009 at 10:28:50AM +1000, Alexander Klenin wrote: > > 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.

And I assume that by "lack of iterators" you mean in-language iterators?

Of course. What else?

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.

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.

Show quoted text 5 lines
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.

Show quoted text 8 lines
> > 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.

> 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']

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.

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

Reply by email

Martin Friebe
to Marco van de Voort: No it doesn't IMHO. And I assume that by "lack of iterators" you mean in-language…
Marco van de Voort wrote 9 lines
On Thu, Mar 26, 2009 at 10:28:50AM +1000, Alexander Klenin wrote: > 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

Reply by email

Reenen Laurie
to Martin Friebe

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
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://www.lazarus.freepascal.org/pipermail/lazarus/attachments/20090326/76c7195b/attachment.html

Reply by email

Graeme Geldenhuys
to Hans-Peter Diettrich: The storage of class instances can be modified by overriding the according methods. I did…
Hans-Peter Diettrich wrote
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/

Reply by email

Graeme Geldenhuys
to Marco van de Voort: No it doesn't IMHO. And I assume that by "lack of iterators" you mean in-language…
Marco van de Voort wrote 6 lines
> > 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/

Reply by email

Graeme Geldenhuys
to Alexander Klenin: This is really nice argument ;-) Well, it _should_ solve it. If it does not, it must be…
Alexander Klenin wrote
> 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.

Show quoted text 10 lines
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/

Reply by email

Marco van de Voort
to Alexander Klenin: This is really nice argument ;-) Well, it _should_ solve it. If it does not, it must be…
Alexander Klenin wrote 9 lines
>> 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. > 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.

Show quoted text 12 lines
> 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.

Show quoted text 8 lines
> 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)

Show quoted text 7 lines
> 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.

And of course cases should not be localised.

And that is odd. Nearly every constant string nowdays is localised sooner or later.

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.

Show quoted text 6 lines
> 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.

Show quoted text 16 lines
>> 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;

Minus one btw.

Show quoted text 10 lines
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.

Show quoted text 5 lines
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.

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.

Show quoted text 6 lines
[regarding 'case of string'] > 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.

Show quoted text 5 lines
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.

> 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).

Reply by email

Marco van de Voort
to Martin Friebe: True,... anyway, best argument(s) I think I saw for string case so far: 1) Readability. I…
Martin Friebe wrote 15 lines
Marco van de Voort wrote: >> 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. 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?

Exactly. Also the alternative presented wasn't if then nesting, but rather a library routine that is like a POS for array of string.

2) Optimizations: 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.

Show quoted text 5 lines
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.

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.

Reply by email

Marco van de Voort
to Graeme Geldenhuys: Iterators are quite doable with all the base list/container classes. I wrote a few months…
Graeme Geldenhuys wrote 11 lines
>> >> 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 ).

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.

Reply by email

Graeme Geldenhuys
to Marco van de Voort: Well, first must be determined if in-language iterator is mandatory, or if runtime…
Marco van de Voort wrote 9 lines
> 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/

Reply by email

Marc Weustink
to Alexander Klenin: This is really nice argument ;-) Well, it _should_ solve it. If it does not, it must be…
Alexander Klenin wrote 21 lines
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.

ehm, what if I want it reversed ?

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

Marc

Reply by email

Alexander Klenin
to Marc Weustink
Marc Weustink wrote 24 lines
Alexander Klenin wrote: > 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. 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.

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

Reply by email

Graeme Geldenhuys
to Alexander Klenin
Alexander Klenin wrote 11 lines
>> ... >> 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/

Reply by email

Paul Ishenin
to Alexander Klenin: Reverse iteration might be common enough to warrant a special syntax, but in general all…
Alexander Klenin wrote
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.

Reply by email

Alexander Klenin
to Paul Ishenin
Paul Ishenin wrote 10 lines
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.

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 -------------- next part -------------- A non-text attachment was scrubbed... Name: iter.pp Type: application/octet-stream Size: 1506 bytes Desc: not available Url : http://www.lazarus.freepascal.org/pipermail/lazarus/attachments/20090327/5c8b4010/attachment.obj

Reply by email

Richard Ward
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.

Reply by email

Dariusz Mazur
to Graeme Geldenhuys: External iterators without the need for implementing descendants. But I must agree, it…

HI
Sorry, this shuld be new topic on pascal devel list, but on other side this is reply on those post.

Show quoted text 44 lines
On Thu, Mar 26, 2009 at 12:29 PM, Alexander Klenin wrote: >> 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. > 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

Reply by email

Lord Satan
to Marco van de Voort: Well, I ported decal, and have a special case in lightcontainers. , and both have library…
> 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?

Reply by email

Marco van de Voort
to Graeme Geldenhuys: And my iterator case is proven. :-) Like I said earlier - one of the reasons I…
Graeme Geldenhuys wrote 13 lines
>> ?? 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.

Reply by email

Hans-Peter Diettrich
to Alexander Klenin: On Thu, Mar 26, 2009 at 17:56, Hans-Peter Diettrich Note that I said "with defined…
Show quoted text 7 lines
>> 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

Reply by email

Paul Nicholls
to Graeme Geldenhuys: Iterators are quite doable with all the base list/container classes. I wrote a few months…

----- Original Message -----

Earlier message 35 lines
From: "Graeme Geldenhuys" Newsgroups: gmane.comp.ide.lazarus.general To: "General mailing list" Sent: Thursday, March 26, 2009 10:50 PM Subject: Re: Easiest way to "case" strings > On Thu, Mar 26, 2009 at 10:59 AM, Marco van de Voort > wrote: >>> > 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

Reply by email

Hans-Peter Diettrich
to Alexander Klenin: This is really nice argument ;-) Well, it _should_ solve it. If it does not, it must be…
Show quoted text 5 lines
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.

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...

Show quoted text 7 lines
[regarding 'case of string'] > 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

Reply by email

Hans-Peter Diettrich
to Graeme Geldenhuys: External iterators without the need for implementing descendants. But I must agree, it…
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.

Show quoted text 6 lines
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.

Show quoted text 5 lines
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

Reply by email

Graeme Geldenhuys
to Hans-Peter Diettrich
Hans-Peter Diettrich wrote 9 lines
> 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!

Show quoted text 10 lines
> 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 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.

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.

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/

Reply by email

Sayyid Ibnu Husein Alatas
to Paul Nicholls: ----- Original Message ----- From: "Graeme Geldenhuys" Newsgroups:…

________________________________

Earlier message 28 lines
From: "Graeme Geldenhuys" 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 -------------- next part -------------- An HTML attachment was scrubbed... URL: http://www.lazarus.freepascal.org/pipermail/lazarus/attachments/20090327/daeb259d/attachment.html

Reply by email

Alexander Klenin
to Hans-Peter Diettrich: This (and the Peek methods) require that the collection is organized strictly sequential,…

On Fri, Mar 27, 2009 at 11:22, Hans-Peter Diettrich 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

Reply by email

Graeme Geldenhuys
to Alexander Klenin
Alexander Klenin wrote
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.

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/

Reply by email

Alexander Klenin
to Hans-Peter Diettrich: The same for strings, where mere binary (case sensitive) equality often is useless.…
Hans-Peter Diettrich wrote 5 lines
> 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.

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.

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'.

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' ;-)

Show quoted text 7 lines
> [regarding 'case of string'] >> 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?

I.e. what's the literal value and representation of the case label for an record?

Record constant of course.

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

Reply by email

Alexander Klenin
to Graeme Geldenhuys: The article was written for a magazine so I do not have the rights to publicly publish it…
Graeme Geldenhuys wrote
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

Reply by email

Graeme Geldenhuys
to Alexander Klenin
Alexander Klenin wrote
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/

Reply by email

Graeme Geldenhuys
to Alexander Klenin: On Fri, Mar 27, 2009 at 18:49, Graeme Geldenhuys It is not that, I just wanted to note…
Alexander Klenin wrote 7 lines
> 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/

Reply by email

Marco van de Voort
to Hans-Peter Diettrich: This (and the Peek methods) require that the collection is organized strictly sequential,…
Hans-Peter Diettrich wrote 8 lines
Graeme Geldenhuys schrieb: > 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.

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))

Show quoted text 8 lines
> 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.

Show quoted text 10 lines
After Remove it has to represent the next or previous item, depending on the direction of traversion. > 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)

Reply by email