Recent

Author Topic: [SOLVED] Using records inside the class  (Read 651 times)

julkas

  • New member
  • *
  • Posts: 46
  • Lazarus 2.0.0 / FPC 3.0.4
[SOLVED] Using records inside the class
« on: April 23, 2019, 08:43:35 pm »
Reading fcl-stl gset implementation on GitHub I found that gset class contains pointer to the record. Why usage of records in the class? Why just not standard class fields?
Code: Pascal  [Select]
  1. generic TSet<T, TCompare>=class
  2.   public
  3.   type
  4.     PNode=^Node;
  5.     Node=record
  6.       Data:T;
  7.       Left,Right:PNode;
  8.       Parent:PNode;
  9.       Color:boolean;
  10.     end;
  11.     TIterator=specialize TSetIterator<T, Node>;
  12.   var
  13.   private
  14.     FBase:PNode;
  15.     FSize:SizeUInt;

BTW FSize is outside the record!

Thanks.
« Last Edit: April 24, 2019, 07:19:22 pm by julkas »
KISS principle

lucamar

  • Hero Member
  • *****
  • Posts: 1464
Re: Using records inside the class
« Reply #1 on: April 23, 2019, 11:06:49 pm »
My guess (and it's just a guess, i've not eye-grepped the code) is it's using a quite standard double-linked list and the implementor found easier to GetMem() for a whole record. I woul probably have the done the same if my surmise is correct.
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus 1.8.4 & 2.0.2 w/FPC 3.0.4 on:
(K|L)Ubuntu 12..16, Windows XP SP3, various DOSes.

ASerge

  • Hero Member
  • *****
  • Posts: 1221
Re: Using records inside the class
« Reply #2 on: April 24, 2019, 12:00:18 am »
I agree with @lucamar. For each element, a record is used, and class fields are used to manage the entire set.

julkas

  • New member
  • *
  • Posts: 46
  • Lazarus 2.0.0 / FPC 3.0.4
Re: Using records inside the class
« Reply #3 on: April 24, 2019, 09:25:31 am »
it's using a quite standard double-linked list and the implementor found easier to GetMem() for a whole record.

1. I think OO implementation of standard double-linked list is more readable, extendable and customizable.
2. There must be other reasons (memory, performance,...)
3. Using records in classes in wrong place and way breaks OO spirit and design.

Any idea, thoughts?

Thanks.
KISS principle

Thaddy

  • Hero Member
  • *****
  • Posts: 7884
Re: Using records inside the class
« Reply #4 on: April 24, 2019, 09:35:41 am »
Any idea, thoughts?
fcl-stl is not exactly the best implementation -its interface is! -. It tries to mimic a C++ style standard template library..
FPC/Lazarus has at least two standard libraries that are - implementation wise - much better:
- fgl
- rtl-generics.

Furthermore these are - but this is my opinion - much easier to use.

People coming from other languages often make the mistake to go for FCL-stl instead of RTL-generics (or for 3.0.4 and before: fgl.) because it contains a magic word: stl. But it should not contain that magic word.
That said: with some effort it could achieve what it advertises.

Quote
1. I think OO implementation of standard double-linked list is more readable, extendable and customizable.
A TList or a TList<T> are underneath linked lists, just like in C.
Quote
2. There must be other reasons (memory, performance,...)
No. The only reasons are OOP in the first place: A linked list isn't. It's a list of pointers, a.k.a. memory locations.
IOW very low-level. OOP is about high-level abstractions.
Quote
3. Using records in classes in wrong place and way breaks OO spirit and design.
You do not understand the encapsulation part of object orientation.
Structures or variables in general can be tightly coupled to a class they belong to.
That's an asset. Not a hindrance.
« Last Edit: April 24, 2019, 09:59:46 am by Thaddy »
Hamlet 1.4 (nothing wrong with the Danish, btw)

mas steindorff

  • Sr. Member
  • ****
  • Posts: 412
Re: Using records inside the class
« Reply #5 on: April 24, 2019, 09:55:25 am »
I like to use records inside my classes as well for 2 reasons. 

1st it shows a variable that may have a common name is truly the one I have defined in the class (like index or tag... my.index, my.tag) or simply to avoid function call vis var like fileExsit vis my.fileExsit

2nd I may wish to use a property field to limit access to a variable now that I will replace with a set and get function later.  Or I only wish to give it read only access outside the class. In my code I know I will have full access to the core variable so I can read and write it as needed.

Example
...tmyclass = class
... my = record
  Count :int64;
  Index :int64;
...
End ; //of record
Public

Property count :int64 read my.count; 
...
End; //of class
windows 7/10 - laz 2.0 / 1.2.6 general releases

Thaddy

  • Hero Member
  • *****
  • Posts: 7884
Re: Using records inside the class
« Reply #6 on: April 24, 2019, 10:01:17 am »
I like to teach whatever my computer science knowledge can bring to other programmers.
That's not perfect, but usually correct.

So, Max you are correct.
« Last Edit: April 24, 2019, 10:04:25 am by Thaddy »
Hamlet 1.4 (nothing wrong with the Danish, btw)

julkas

  • New member
  • *
  • Posts: 46
  • Lazarus 2.0.0 / FPC 3.0.4
Re: Using records inside the class
« Reply #7 on: April 24, 2019, 10:24:05 am »
fcl-stl is not exactly the best implementation -its interface is! -. It tries to mimic a C++ style standard template library..
FPC/Lazarus has at least two standard libraries that are - implementation wise - much better:
- fgl
- rtl-generics.

OK. My question is not from the user side, but from learner and programmer. I try to understand pros and cons of gset implementation.

Why not simply -

Code: Pascal  [Select]
  1. generic TSet<T, TCompare>=class
  2.   public
  3.       Data:T;
  4.       Left,Right:TSet;
  5.       Parent:TSet;
  6.       Color:boolean;
  7.       FSize:SizeUInt;
« Last Edit: April 24, 2019, 11:14:25 am by julkas »
KISS principle

Thaddy

  • Hero Member
  • *****
  • Posts: 7884
Re: Using records inside the class
« Reply #8 on: April 24, 2019, 11:50:43 am »
Well, the public part is not immediately correct, if you mean that.
Records declared inside of a class should not have the possibility to be accessed outside of that class or (when protected) outside of inherited classes.

There are cases, though, that warrant it. These are rare.

You are asking the right questions...

Scope is essentially what prevents you from making mistakes.
« Last Edit: April 24, 2019, 12:00:34 pm by Thaddy »
Hamlet 1.4 (nothing wrong with the Danish, btw)

creaothceann

  • Full Member
  • ***
  • Posts: 109
Re: Using records inside the class
« Reply #9 on: April 24, 2019, 06:48:19 pm »
OO spirit and design
OO is just one tool. Tools are specific to their use cases, and you have to know when to switch tools. There is no silver bullet.

(OO is frequently not used for example in high-performance game programming because OO often groups data unrelated to the current job together, i.e. the fields of an object are all bundled in one memory location, wasting the cache space of modern CPUs.)

mas steindorff

  • Sr. Member
  • ****
  • Posts: 412
Re: Using records inside the class
« Reply #10 on: April 24, 2019, 08:09:06 pm »
OK. My question is not from the user side, but from learner and programmer. I try to understand pros and cons of gset implementation.
well, one "pro" to this is by by placing all of my variables in a record, I can use a call to fillchar(my,sizeof(my),0) => "fill memory with 0" in my Clear() procedure. My warning anyone using this trick is you can only have simple variables in your record. Strings, classes, and even arrays defined within the record should not be cleared in this manor so I keep them outside the record.

this trick lets me add more variables and not worry about re-init each one in either the class.create or .clear procedures.

it's also simpler to create a class.Assign().  I can copy all of the variables with a one liner self.my := src.my;  and then go in and modify the ones I need to.   

windows 7/10 - laz 2.0 / 1.2.6 general releases

marcov

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 6993
Re: Using records inside the class
« Reply #11 on: April 24, 2019, 10:56:44 pm »
A TList or a TList<T> are underneath linked lists, just like in C.

Nope, basically just array wrappers.

PascalDragon

  • Sr. Member
  • ****
  • Posts: 329
  • Compiler Developer
Re: [SOLVED] Using records inside the class
« Reply #12 on: April 25, 2019, 12:11:33 pm »
Reading fcl-stl gset implementation on GitHub I found that gset class contains pointer to the record. Why usage of records in the class? Why just not standard class fields?
Code: Pascal  [Select]
  1. generic TSet<T, TCompare>=class
  2.   public
  3.   type
  4.     PNode=^Node;
  5.     Node=record
  6.       Data:T;
  7.       Left,Right:PNode;
  8.       Parent:PNode;
  9.       Color:boolean;
  10.     end;
  11.     TIterator=specialize TSetIterator<T, Node>;
  12.   var
  13.   private
  14.     FBase:PNode;
  15.     FSize:SizeUInt;

BTW FSize is outside the record!

Thanks.
It seems that you misunderstand what is happening here. Node is not a field, it's a type. It would logically be equal to declare Node outside of TSet<,>. This way TSet<,> can contain multiple Node entries by using a linked list which is much less expensive than doing a linked list for the whole class. And the FSize is simply there to keep track of the amount of items without the need to iterate the whole linked list.

julkas

  • New member
  • *
  • Posts: 46
  • Lazarus 2.0.0 / FPC 3.0.4
Re: [SOLVED] Using records inside the class
« Reply #13 on: April 25, 2019, 05:43:59 pm »
It seems that you misunderstand what is happening here. Node is not a field, it's a type. It would logically be equal to declare Node outside of TSet<,>. This way TSet<,> can contain multiple Node entries by using a linked list which is much less expensive than doing a linked list for the whole class. And the FSize is simply there to keep track of the amount of items without the need to iterate the whole linked list.
Ok. Thanks. I got it. I am writing implementation of similar data structure without records. Node is instance of class in my code and all operations are class methods. This approach has overheads, but works good and fast. Gset instance holds only  pointer to the root node.  But my question remains.
KISS principle

garlar27

  • Hero Member
  • *****
  • Posts: 593
Re: Using records inside the class
« Reply #14 on: April 25, 2019, 05:52:04 pm »
OK. My question is not from the user side, but from learner and programmer. I try to understand pros and cons of gset implementation.
well, one "pro" to this is by by placing all of my variables in a record, I can use a call to fillchar(my,sizeof(my),0) => "fill memory with 0" in my Clear() procedure. My warning anyone using this trick is you can only have simple variables in your record. Strings, classes, and even arrays defined within the record should not be cleared in this manor so I keep them outside the record.

@mas steindorff:
Look at this thread "Weird Memory Leak!!". Martin_fr suggested to use this code:
Code: Pascal  [Select]
  1. procedure FillerByte(out x; count: SizeInt; value: byte);
  2. begin
  3.    FillByte(x, count, value);
  4. end;
  5.  
And now I can't live without that code (by the way this month was the birthday of such a great procedure, now it has 7 years and 20 days old  :D )