Recent

Author Topic: Tlist problem  (Read 6605 times)

lazer

  • Full Member
  • ***
  • Posts: 215
Tlist problem
« on: October 07, 2017, 12:38:33 pm »
Hi,

I have done quite a lot of TP and Delphi, but it's was a long time ago and I'm having trouble using a Tlist.

I want to use it to store a list of integers. Simple enough.

I added a Tlist to the form , thinking that this would get it an instance of Tlist.
Code: Pascal  [Select][+][-]
  1.  private
  2.     { private declarations }
  3.   public
  4.     testx:integer;
  5.     digits:Tlist;
  6.  

However, when I try to use it in FormCreate() it is null and causes an exception.
Code: Pascal  [Select][+][-]
  1. procedure TForm1.FormCreate(Sender: TObject);
  2. begin
  3.    digits.clear;
  4. end;
  5.  
  6.  

What am I missing?

thanks.

balazsszekely

  • Guest
Re: Tlist problem
« Reply #1 on: October 07, 2017, 12:41:29 pm »
Hi lazer,

You have to create the list and make sure you free it on form destroy, to prevent memory leaks:
Code: Pascal  [Select][+][-]
  1. //...
  2.  
  3. procedure TForm1.FormCreate(Sender: TObject);
  4. begin
  5.   Digits := TList.Create;
  6. end;
  7.  
  8. procedure TForm1.FormDestroy(Sender: TObject);
  9. begin
  10.   Digits.Free;
  11. end;

Handoko

  • Hero Member
  • *****
  • Posts: 5158
  • My goal: build my own game engine using Lazarus
Re: Tlist problem
« Reply #2 on: October 07, 2017, 01:03:16 pm »
The TList documentation:
https://www.freepascal.org/docs-html/rtl/classes/tlist.html

Anyone looking for tutorial for TList (suitable for newbies), you may start reading from here:
http://forum.lazarus.freepascal.org/index.php/topic,38136.msg260867.html#msg260867

apexcol

  • Jr. Member
  • **
  • Posts: 54
Re: Tlist problem
« Reply #3 on: February 11, 2018, 10:02:26 am »
Sorry for being late... but here is an answer for the new ones (I was lost also some time ago) ;)

Code: Pascal  [Select][+][-]
  1. implementation
  2. type
  3.   pLongInt = ^LongInt;
  4.  
  5. {$R *.lfm}
  6.  
  7. procedure TForm1.Button1Click(Sender: TObject);
  8. var
  9.   t: Tlist;
  10.   l: longint;
  11. begin
  12.   T := tlist.create;
  13.   L := 123;
  14. //// I can store a "crude" pointer:  t.add(pointer(@L));
  15.   T.add(@l); /// and you can also use:  t.add(pLongint(@L));
  16.   Caption := IntToStr(pLongInt(T.items[0])^);
  17. /// to take it out it can be also:  
  18. /// caption := intToStr(integer(pointer(T.items[0])^));
  19.   T.free;
  20. end;
  21.  
Enjoy! :D

Thaddy

  • Hero Member
  • *****
  • Posts: 14382
  • Sensorship about opinions does not belong here.
Re: Tlist problem
« Reply #4 on: February 11, 2018, 10:49:06 am »
A much better way for anyone new to Object Pascal is using one of the generics options.
One: use fgl;
Code: Pascal  [Select][+][-]
  1. program listtest;
  2. {$mode delphi}
  3. uses fgl;
  4. var
  5.   List:TFPGlist<integer>;
  6.   i:integer;
  7. begin
  8.   List := TFPGList<integer>.create;
  9.   try
  10.     List.Add(1);
  11.     List.Add(2);
  12.     for i in list do
  13.       writeln(i);
  14.   finally
  15.     List.Free;
  16.   end;
  17. end.

Two: (trunk): use rtl-generics:
Code: Pascal  [Select][+][-]
  1. program listtest;
  2. {$mode delphi}
  3. uses generics.collections;
  4. var
  5.   List:Tlist<integer>;
  6.   i:integer;
  7. begin
  8.   List := TList<integer>.create;
  9.   try
  10.     List.Add(1);
  11.     List.Add(2);
  12.     for i in list do
  13.       writeln(i);
  14.   finally
  15.     List.Free;
  16.   end;
  17. end.

This important because you do not have to fight with un-typed things.
The above example code will then translate into:
Code: Pascal  [Select][+][-]
  1. procedure TForm1.Button1Click(Sender: TObject);
  2. var
  3.   t: TFPGlist<integer>;
  4.   l: longint;
  5. begin
  6.   t := TFPGList<integer>.create;
  7.   try // try to program defensive
  8.     L := 123;
  9.     t.add(L);
  10.     t.add(1);
  11.     Caption := T[0].ToString;  // also a newer feature that makes things readable and concise. Also in 3.0.4. requires sysutils
  12.   finally  
  13.     t.free;
  14.   end;
  15. end;
Note this assumes your unit is in {$mode delphi}.
In {$mode objfpc} it looks like this:
Code: Pascal  [Select][+][-]
  1. procedure TForm1.Button1Click(Sender: TObject);
  2. var
  3.   t: specialize TFPGlist<integer>;
  4.   l: longint;
  5. begin
  6.   t := specialize TFPGList<integer>.create;
  7.   try // try to program defensive
  8.     L := 123;
  9.     t.add(L);
  10.     t.add(1);
  11.     Caption := T[0].ToString;  // also a newer feature that makes things readable and concise. Also in 3.0.4
  12.   finally  
  13.     t.free;
  14.   end;
  15. end;

The old Tlist (un-typed) from classes should not be considered obsolete, but as of the current Freepascal 3.0.4 should be considered for advanced programmers only.
Its use for beginners should be discouraged. Pascal is a strongly typed language after all...
« Last Edit: February 11, 2018, 11:24:28 am by Thaddy »
Object Pascal programmers should get rid of their "component fetish" especially with the non-visuals.

WooBean

  • Full Member
  • ***
  • Posts: 231
Re: Tlist problem
« Reply #5 on: February 11, 2018, 12:08:10 pm »
Hi,
as a newbie I tried to get advantage of learning from the TList topic.
Most teaching examples came from Thaddy, however for me two questions remains:

1. How can I make working example "Two: (trunk): use rtl-generics:"? - I get compiler error "project1.lpr(3,6) Fatal: Cannot find generics.collections used by listtest. Check if package sparta_Generics is in the dependencies.".

2. Using  for-in-loop syntax (see http://wiki.freepascal.org/for-in_loop) makes me to feel uneasy as it is extremally easy to make errors in code and difficult to pinpoint them next. I think that spirit of Pascal doesn't like it.
Platforms: Win7/64, Linux Mint Ulyssa/64

Thaddy

  • Hero Member
  • *****
  • Posts: 14382
  • Sensorship about opinions does not belong here.
Re: Tlist problem
« Reply #6 on: February 11, 2018, 12:36:49 pm »
I explicitly explained that rtl-generics are only in trunk |(3.1.1).
I suggest to use the fgl example for now if you are a beginner, although it is possible to install an older sparta package separately. rtl-generics are based on that, but much more advanced due to new compiler features.

Just use fgl for now if you are a real beginner: the functionality and syntax are similar. As I showed.

The use of trunk is also possible and easiest to install using fpcupdeluxe. If you are adventurous and want the latest features.

ad 2: no, on the contrary: for in do prevents you from making mistakes in code because it protects you from introducing range errors. If possible always use for in do instead of for i := x to y...
The reason is that you can make a mistake with x or y or both and it will crash your code.
For in do automatically prevents you from making such a mistake.
example:
Code: Pascal  [Select][+][-]
  1. program buggy;
  2. {$mode delphi}
  3. var
  4.   test:array of integer;
  5.   i:integer;
  6. begin
  7.   Test:=Test.Create(1,2,3,4,5,6,7,8,9,10); //10 elements
  8.   for i :=  1 to 10 do
  9.     writeln(Test[i]); // wrong! but do you know why?
  10. end.

As opposed to
Code: Pascal  [Select][+][-]
  1. program lessbuggy;
  2. {$mode delphi}
  3. var
  4.   test:array of integer;
  5.   i:integer;
  6. begin
  7.   Test:=Test.Create(1,2,3,4,5,6,7,8,9,10); //10 elements
  8.   for i in test do
  9.     writeln(i); // writes the array element !!
  10. end.



« Last Edit: February 11, 2018, 01:39:16 pm by Thaddy »
Object Pascal programmers should get rid of their "component fetish" especially with the non-visuals.

WooBean

  • Full Member
  • ***
  • Posts: 231
Re: Tlist problem
« Reply #7 on: February 11, 2018, 01:18:40 pm »
@Thaddy

at 1. Thanks, and then thanks (trunk may stay away).
at 2. I'll stay by my own opinion about using "for in" - range iteration error is not a problem, the real problem is that you code "writeln(i);" but in fact you have
Code: Pascal  [Select][+][-]
  1.  writeln(List.Items[i]);
If someting is wrong I (and everyone else) can jump into "Item" "Items" default property or "List" variable. And this is a power of old style Pascal.     
« Last Edit: February 11, 2018, 01:41:51 pm by WooBean »
Platforms: Win7/64, Linux Mint Ulyssa/64

Thaddy

  • Hero Member
  • *****
  • Posts: 14382
  • Sensorship about opinions does not belong here.
Re: Tlist problem
« Reply #8 on: February 11, 2018, 01:31:16 pm »
Then you do not understand the new language features at all.
Anyway you are partially right that I made a mistake my self and I updated the example with comments.
Brain compiler failed.
« Last Edit: February 11, 2018, 01:40:45 pm by Thaddy »
Object Pascal programmers should get rid of their "component fetish" especially with the non-visuals.

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 11458
  • FPC developer.
Re: Tlist problem
« Reply #9 on: February 11, 2018, 02:02:15 pm »
(well, even Delphi debugger seems to have more troubles walking structures involved in a for..in than a handwritten loop)

Thaddy

  • Hero Member
  • *****
  • Posts: 14382
  • Sensorship about opinions does not belong here.
Re: Tlist problem
« Reply #10 on: February 11, 2018, 02:57:36 pm »
Well Marco, brain compiler would probably not have failed with simple
Code: Pascal  [Select][+][-]
  1. for i := Low(test) to High(test) do writeln(test[i]);
which is also defensive.
Object Pascal programmers should get rid of their "component fetish" especially with the non-visuals.

engkin

  • Hero Member
  • *****
  • Posts: 3112
Re: Tlist problem
« Reply #11 on: February 11, 2018, 03:40:32 pm »
Sorry for being late... but here is an answer for the new ones (I was lost also some time ago) ;)

Code: Pascal  [Select][+][-]
  1. [snipped]
  2. procedure TForm1.Button1Click(Sender: TObject);
  3. var
  4.   t: Tlist;
  5.   l: longint;
  6. begin
  7.   T := tlist.create;
  8.   L := 123;
  9. //// I can store a "crude" pointer:  t.add(pointer(@L));
  10.   T.add(@l); /// and you can also use:  t.add(pLongint(@L));
Notice that variable l is reserved on the stack. Its address @l is valid only inside this method. On the other hand you can save the integer value directly in the list using a simple typecast t.add(pointer(L)).

Anyway, I agree with Thaddy. He showed better alternatives for "the new ones".

WooBean

  • Full Member
  • ***
  • Posts: 231
Re: Tlist problem
« Reply #12 on: February 11, 2018, 06:36:58 pm »
@Thaddy

In response to
Then you do not understand the new language features at all.
Anyway you are partially right that I made a mistake my self and I updated the example with comments.
Brain compiler failed.

I would like to thank for your psychiatric diagnosis, not requested or expected however.
Platforms: Win7/64, Linux Mint Ulyssa/64

Thaddy

  • Hero Member
  • *****
  • Posts: 14382
  • Sensorship about opinions does not belong here.
Re: Tlist problem
« Reply #13 on: February 11, 2018, 07:12:21 pm »
Use the new features. They are safer. I did not mean to offend, but you clearly had an opinion rooted in the past. AND tnx for spotting my bug again..
Object Pascal programmers should get rid of their "component fetish" especially with the non-visuals.

apexcol

  • Jr. Member
  • **
  • Posts: 54
Re: Tlist problem
« Reply #14 on: February 12, 2018, 12:02:21 am »
No problem, I think these kind of debates help others to learn better our nice language :)

 

TinyPortal © 2005-2018