Recent

Author Topic: Beginner string list problem  (Read 818 times)

rnfpc

  • Jr. Member
  • **
  • Posts: 91
Beginner string list problem
« on: June 20, 2019, 07:25:50 pm »
I have just started using fpc and it is great. I am currently trying to create a string list with followng code:

Code: Pascal  [Select]
  1. program rnstrlist2;
  2. {$mode objfpc}{$H+}
  3. uses fgl;
  4. {from: https://wiki.freepascal.org/Generics }
  5. type
  6.   generic TList<T> = class
  7.     Items: array of T;
  8.     procedure Add(Value: T);
  9.   end;
  10.  
  11. procedure TList.Add(Value: T);
  12. begin
  13.   SetLength(Items, Length(Items) + 1);
  14.   Items[Length(Items) - 1] := Value;
  15. end;
  16.  
  17. Type  
  18.   TStringList = specialize TList<string>;
  19. var
  20.         mystrlist : Tstringlist;
  21.         item: string;
  22. begin
  23.         mystrlist := Tstringlist.create;
  24.         setlength(mystrlist, 3);
  25.         mystrlist.add('one');
  26.         mystrlist.add('two');
  27.         mystrlist.add('three');
  28.         for item in mystrlist do
  29.                 writeln(item);
  30.  
  31. end.
  32.  
However, it is giving following error:

Quote
$fpc soq_rnstrlist2
Free Pascal Compiler version 3.0.0+dfsg-11+deb9u1 [2017/06/10] for x86_64
Copyright (c) 1993-2015 by Florian Klaempfl and others
Target OS: Linux for x86-64
Compiling soq_rnstrlist2.pas
soq_rnstrlist2.pas(28,2) Error: Type mismatch
soq_rnstrlist2.pas(32,14) Error: Cannot find an enumerator for the type "TList$1$crcAC3AF268"
soq_rnstrlist2.pas(38) Fatal: There were 2 errors compiling module, stopping
Fatal: Compilation aborted
Error: /usr/bin/ppcx64 returned an error exitcode
Where is the problem and how can it be corrected?

Handoko

  • Hero Member
  • *****
  • Posts: 3103
  • My goal: build my own game engine using Lazarus
Re: Beginner string list problem
« Reply #1 on: June 20, 2019, 07:34:25 pm »
Hello rnfpc,
Welcome to the forum.

I've fixed it. This below works, can you see the differences?

Code: Pascal  [Select]
  1. program rnstrlist2;
  2. {$mode objfpc}{$H+}
  3. uses fgl, sysutils;
  4. {from: https://wiki.freepascal.org/Generics }
  5. type
  6.   generic TList<T> = class
  7.     Items: array of T;
  8.     procedure Add(Value: T);
  9.   end;
  10.  
  11. procedure TList.Add(Value: T);
  12. begin
  13.   SetLength(Items, Length(Items) + 1);
  14.   Items[Length(Items) - 1] := Value;
  15. end;
  16.  
  17. Type
  18.   TStringList = specialize TList<string>;
  19. var
  20.         mystrlist : Tstringlist;
  21.         item: string;
  22. begin
  23.         mystrlist := Tstringlist.create;
  24.         mystrlist.add('one');
  25.         mystrlist.add('two');
  26.         mystrlist.add('three');
  27.         for item in mystrlist.Items do
  28.                 writeln(item);
  29.  
  30. end.

rnfpc

  • Jr. Member
  • **
  • Posts: 91
Re: Beginner string list problem
« Reply #2 on: June 20, 2019, 07:38:59 pm »
Great. The differences are:

* sysutils have been added in uses;
* for item in mystrlist.Items : .Items has been added
* setlength has been removed from last (main) block since it is already there in TList.Add procedure

I look forward to your explanations.

Handoko

  • Hero Member
  • *****
  • Posts: 3103
  • My goal: build my own game engine using Lazarus
Re: Beginner string list problem
« Reply #3 on: June 20, 2019, 07:41:04 pm »
Sorry, sysutils is not need. My fault.  :-X

lucamar

  • Hero Member
  • *****
  • Posts: 1962
Re: Beginner string list problem
« Reply #4 on: June 21, 2019, 12:01:57 am »
* for item in mystrlist.Items : .Items has been added

That's the really important part: TList by itself dosn't implement and enumerator, so you can't use "for item in mystrlist do ..." unless you add one *or* (I think) implement Items as a default property of the TList, because ...

Arrays do have an intrinsic enumerator, so "for item in mystrlist.Items do ..." works as it should.
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus 2.0.2/2.0.4  - FPC 3.0.4 on:
(K|L)Ubuntu 12..16, Windows XP SP3, various DOSes.

Mr.Madguy

  • Sr. Member
  • ****
  • Posts: 442
Re: Beginner string list problem
« Reply #5 on: June 21, 2019, 08:37:03 am »
Not sure about Lazarus, but in Delphi you need to implement your enumerator and static GetEnumerator method:
Code: Pascal  [Select]
  1. function TMyCollection.GetEnumerator: TMyCollectionEnumerator;
  2. begin
  3.   Result := TMyCollectionEnumerator.Create(Self);
  4. end;
  5.  

Code: Pascal  [Select]
  1. type
  2.   TMyCollectionEnumerator = class
  3.   protected
  4.     Parent: TMyCollection;
  5.     Position: integer;
  6.   public
  7.     constructor Create(AParent: TMyCollection);
  8.     function MoveNext: boolean;
  9.     function GetCurrent: integer;
  10.     property Current: integer read GetCurrent;
  11.   end;
  12.  
Many major changes - Version has been changed to 3.0!
Crazy unit testing
Lack of multiple inheritance turns it into abomination.

mangakissa

  • Hero Member
  • *****
  • Posts: 927
Re: Beginner string list problem
« Reply #6 on: June 21, 2019, 09:05:04 am »
Code: Pascal  [Select]
  1. Type  
  2.   TStringList = specialize TList<string>;
  3. var
  4.         mystrlist : Tstringlist;
  5.  
Is this working when FPC already has a TStringlist defined in unit classes?
Lazarus 1.84 (32b) / FPC 3.0.4
Windows 10

PascalDragon

  • Hero Member
  • *****
  • Posts: 523
  • Compiler Developer
Re: Beginner string list problem
« Reply #7 on: June 21, 2019, 09:06:44 am »
I have just started using fpc and it is great. I am currently trying to create a string list with followng code:
Two points:
As you're already using the FGL unit you could simply do TStringList = specialize TFPGList<String>;.
Alternatively you can use the existing TStringList class from the Classes unit.

Though of course I understand if you simply want to try things out to learn how they work. ;)

Code: Pascal  [Select]
  1. Type  
  2.   TStringList = specialize TList<string>;
  3. var
  4.         mystrlist : Tstringlist;
  5.  
Is this working when FPC already has a TStringlist defined in unit classes?
The Classes unit is not used in the provided example code, so the compiler wouldn't find that anyway. But even if the Classes unit was used local symbols are found before symbols provided by units (and used units are searched right to left).

julkas

  • Sr. Member
  • ****
  • Posts: 314
  • KISS principle / Lazarus 2.0.0 / FPC 3.0.4
Re: Beginner string list problem
« Reply #8 on: July 21, 2019, 01:20:03 pm »
I have just started using fpc and it is great. I am currently trying to create a string list with followng code:

Code: Pascal  [Select]
  1. program rnstrlist2;
  2. {$mode objfpc}{$H+}
  3. uses fgl;
  4. {from: https://wiki.freepascal.org/Generics }
  5. type
  6.   generic TList<T> = class
  7.     Items: array of T;
  8.     procedure Add(Value: T);
  9.   end;
  10.  
  11. procedure TList.Add(Value: T);
  12. begin
  13.   SetLength(Items, Length(Items) + 1);
  14.   Items[Length(Items) - 1] := Value;
  15. end;
  16.  
  17. Type  
  18.   TStringList = specialize TList<string>;
  19. var
  20.         mystrlist : Tstringlist;
  21.         item: string;
  22. begin
  23.         mystrlist := Tstringlist.create;
  24.         setlength(mystrlist, 3);
  25.         mystrlist.add('one');
  26.         mystrlist.add('two');
  27.         mystrlist.add('three');
  28.         for item in mystrlist do
  29.                 writeln(item);
  30.  
  31. end.
  32.  
However, it is giving following error:

Quote
$fpc soq_rnstrlist2
Free Pascal Compiler version 3.0.0+dfsg-11+deb9u1 [2017/06/10] for x86_64
Copyright (c) 1993-2015 by Florian Klaempfl and others
Target OS: Linux for x86-64
Compiling soq_rnstrlist2.pas
soq_rnstrlist2.pas(28,2) Error: Type mismatch
soq_rnstrlist2.pas(32,14) Error: Cannot find an enumerator for the type "TList$1$crcAC3AF268"
soq_rnstrlist2.pas(38) Fatal: There were 2 errors compiling module, stopping
Fatal: Compilation aborted
Error: /usr/bin/ppcx64 returned an error exitcode
Where is the problem and how can it be corrected?
Advice from beginner: use {$mode delphi}, it's more clear for beginners. http://ideone.com/4fClPG. If you want your own generic TList -
Code: Pascal  [Select]
  1. program rnstrlist2;
  2. {$mode delphi}
  3.  
  4. type
  5.   TList<T> = class
  6.     items: array of T;
  7.     procedure Add(value: T);
  8.   end;
  9.      
  10. procedure TList<T>.Add(value: T);
  11.   begin
  12.     SetLength(items, Length(items) + 1);
  13.     items[Length(Items) - 1] := value;
  14.   end;
  15.      
  16. var
  17.   mystrlist: TList<String>;
  18.   item: String;
  19. begin
  20.   mystrlist := TList<String>.Create;
  21.   mystrlist.Add('one');
  22.   mystrlist.Add('two');
  23.   mystrlist.Add('three');
  24.   for item in mystrlist.items do
  25.     WriteLn(item);
  26. end.
« Last Edit: July 21, 2019, 01:33:49 pm by julkas »
procedure mulu64(a, b: QWORD; out clo, chi: QWORD); assembler;
asm
  mov rax, a
  mov rdx, b
  mul rdx
  mov [clo], rax
  mov [chi], rdx
end;
(* Pointer game *) Inc(ptr, 1); (* vs *) ptr := ptr + 1;

julkas

  • Sr. Member
  • ****
  • Posts: 314
  • KISS principle / Lazarus 2.0.0 / FPC 3.0.4
Re: Beginner string list problem
« Reply #9 on: July 21, 2019, 01:47:20 pm »
I have just started using fpc and it is great. I am currently trying to create a string list with followng code:

Code: Pascal  [Select]
  1. program rnstrlist2;
  2. {$mode objfpc}{$H+}
  3. uses fgl;
  4. {from: https://wiki.freepascal.org/Generics }
  5. type
  6.   generic TList<T> = class
  7.     Items: array of T;
  8.     procedure Add(Value: T);
  9.   end;
  10.  
  11. procedure TList.Add(Value: T);
  12. begin
  13.   SetLength(Items, Length(Items) + 1);
  14.   Items[Length(Items) - 1] := Value;
  15. end;
  16.  
  17. Type  
  18.   TStringList = specialize TList<string>;
  19. var
  20.         mystrlist : Tstringlist;
  21.         item: string;
  22. begin
  23.         mystrlist := Tstringlist.create;
  24.         setlength(mystrlist, 3);
  25.         mystrlist.add('one');
  26.         mystrlist.add('two');
  27.         mystrlist.add('three');
  28.         for item in mystrlist do
  29.                 writeln(item);
  30.  
  31. end.
  32.  
However, it is giving following error:

Quote
$fpc soq_rnstrlist2
Free Pascal Compiler version 3.0.0+dfsg-11+deb9u1 [2017/06/10] for x86_64
Copyright (c) 1993-2015 by Florian Klaempfl and others
Target OS: Linux for x86-64
Compiling soq_rnstrlist2.pas
soq_rnstrlist2.pas(28,2) Error: Type mismatch
soq_rnstrlist2.pas(32,14) Error: Cannot find an enumerator for the type "TList$1$crcAC3AF268"
soq_rnstrlist2.pas(38) Fatal: There were 2 errors compiling module, stopping
Fatal: Compilation aborted
Error: /usr/bin/ppcx64 returned an error exitcode
Where is the problem and how can it be corrected?
And if you want fgl - something like this
Code: Pascal  [Select]
  1. program rnstrlist2;
  2. {$mode delphi}
  3. uses fgl;
  4.  
  5. var
  6.   mystrlist: TFPGList<String>;
  7.   item: string;
  8. begin
  9.   mystrlist := TFPGList<String>.Create;
  10.   mystrlist.Add('one');
  11.   mystrlist.Add('two');
  12.   mystrlist.Add('three');
  13.   for item in mystrlist do
  14.     WriteLn(item);
  15. end.
  16.  
procedure mulu64(a, b: QWORD; out clo, chi: QWORD); assembler;
asm
  mov rax, a
  mov rdx, b
  mul rdx
  mov [clo], rax
  mov [chi], rdx
end;
(* Pointer game *) Inc(ptr, 1); (* vs *) ptr := ptr + 1;

totya

  • Hero Member
  • *****
  • Posts: 573
Re: Beginner string list problem
« Reply #10 on: July 21, 2019, 01:57:49 pm »
As you're already using the FGL unit you could simply do TStringList = specialize TFPGList<String>;.

Hi, yes, but from the wiki:

Quote
TFPGList can be used to specialize a list for any type T that does not require reference counting (such as interfaced objects).

My question is, this "specialized" TStringList reference counted or not?

julkas

  • Sr. Member
  • ****
  • Posts: 314
  • KISS principle / Lazarus 2.0.0 / FPC 3.0.4
Re: Beginner string list problem
« Reply #11 on: July 21, 2019, 07:12:24 pm »
procedure mulu64(a, b: QWORD; out clo, chi: QWORD); assembler;
asm
  mov rax, a
  mov rdx, b
  mul rdx
  mov [clo], rax
  mov [chi], rdx
end;
(* Pointer game *) Inc(ptr, 1); (* vs *) ptr := ptr + 1;

totya

  • Hero Member
  • *****
  • Posts: 573
Re: Beginner string list problem
« Reply #12 on: July 21, 2019, 07:15:32 pm »
If you want String list use - https://www.freepascal.org/docs-html/rtl/classes/tstringlist.html

Please stop it... StringList isn't good is any case, for example if the added string contains LineEnding char, and I want to keep this block. Stop these spam please.

jamie

  • Hero Member
  • *****
  • Posts: 1779
Re: Beginner string list problem
« Reply #13 on: July 21, 2019, 10:39:47 pm »
I solved that problem using the String To json function in the json unit..

With that you can use any value character below 32 and have it part of the string without the tstringlist getting confused.
 
 What it does is uses C style strings escape characters so you can  have any value in there and it is still human readable.


lucamar

  • Hero Member
  • *****
  • Posts: 1962
Re: Beginner string list problem
« Reply #14 on: July 21, 2019, 10:57:41 pm »
I solved that problem using the String To json function in the json unit..

With that you can use any value character below 32 and have it part of the string without the tstringlist getting confused.
 
 What it does is uses C style strings escape characters so you can  have any value in there and it is still human readable.

That can also be done with UTF8EscapeControlChars(), from LazUTF8 (LazUtils package) and coding a couple of simple-minded Escape() / Unescape() isn't too difficult either: one just pass the string through a loop doing StringReplace's

But totya is right that the standard TStringList isn't the panacea most people think, and there's nothing wrong in trying to code one's own equivalent.
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus 2.0.2/2.0.4  - FPC 3.0.4 on:
(K|L)Ubuntu 12..16, Windows XP SP3, various DOSes.