Sign in Join

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

Mailing lists / fpc-pascal / 2014-12

cloning data containers

9 messages · 4 people · –

Reply by email Subscribe to this list Your subscription

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

Marc Santhoff

Hi,

I hope you all had nice christmas days and now can answer my question. ;)

Is there any way of cloning record and objects having only data fields? Or do I have to copy the (non reference) fields one by one as usual?

Explanation:

a_record = record
  this: integer;
  that: string;
  ...
end
function clone(data_in: a_record): a_record;
var
  data: Pa_record;
begin
  new(data);
  // here every single data field has to be filled in
  data.this := data_in.this;
  data.that := data_in.that;
  ...
  result := data
end;

When you have to deal with lots of record types and lots of fields this is very boring and maybe exhausting. At least it is error prone without typing support by some automatism in the IDE.

Using MOVE() is not possible execept if using {$PackRecord 1}, which is not always possible and hinders the compiler from generating fast code (me thinks). And morte, if using record types defined elsewhere (e.g. TFindRecord) it is impossible.

For classes the same scheme applies, writing an assign() method and copying each item seperately is a lot of work.

Maybe I have asked this question in the past, but fpc does evolve and there are e.g. record helpers today. Any help for easing my pain? ;)

TIA,
Marc

Marc Santhoff

Reply by email

Bart
to Marc Santhoff
Marc Santhoff wrote 5 lines
function clone(data_in: a_record): a_record; var data: Pa_record; begin new(data);
     data^ := data_in;  //should work*
end;

* Might not be a good idea if data contains a class(reference).

Bart

Reply by email

Marc Santhoff
to Bart
Bart wrote 11 lines
On 12/27/14, Marc Santhoff wrote: > function clone(data_in: a_record): a_record; > var > data: Pa_record; > begin > new(data); data^ := data_in; //should work* > end; * Might not be a good idea if data contains a class(reference).

Oops, I just typed that away and did not hit CTRL-F9 - which is useless in the mailer anyway. ;)

Marc Santhoff

Reply by email

Chriss Kalogeropoulos
to Marc Santhoff

Hi,

FPC does not support copy-construction so either you must override the TPersistent.Assign method or in case of TComponent you can use ReadComponent/WriteComponent.

You should also take into account deep vs swallow copy semantics as well as the type of the container and contained classes
(TPersistent/TCmponent/TCollection descendant).

For records I am not sure, probably you should need a method on the container or check on some internal (compiler magic) functions such as CopyRecord and others.

Hope that helps.

Chriss

"Marc Santhoff" wrote 23 lines
On Sa, 2014-12-27 at 16:45 +0100, Bart wrote: > On 12/27/14, Marc Santhoff wrote: > > > function clone(data_in: a_record): a_record; > > var > > data: Pa_record; > > begin > > new(data); > data^ := data_in; //should work* > > end; > > * Might not be a good idea if data contains a class(reference). Oops, I just typed that away and did not hit CTRL-F9 - which is useless in the mailer anyway. ;) -- Marc Santhoff _______________________________________________ fpc-pascal maillist - http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal

Reply by email

Sven Barth
to Marc Santhoff: I hope you all had nice christmas days and now can answer my question. ;) Is there any…
"Marc Santhoff" wrote
Is there any way of cloning record and objects having only data fields? Or do I have to copy the (non reference) fields one by one as usual?

Shouldn't the normal assignment be enough for any non-reference (aka non-managed pointers) fields?
Meaning first you simply assign your input record to the result (strings, arrays and interfaces will be handled here) and then you update those fields that should be "deep copied".

Regards,
Sven

Reply by email

Marc Santhoff
to Chriss Kalogeropoulos: FPC does not support copy-construction so either you must override the TPersistent.Assign…
Chriss Kalogeropoulos wrote 5 lines
Hi, FPC does not support copy-construction so either you must override the TPersistent.Assign method or in case of TComponent you can use ReadComponent/WriteComponent.

:|

You should also take into account deep vs swallow copy semantics as well as the type of the container and contained classes (TPersistent/TCmponent/TCollection descendant).

TCollection is a good idea. Life could be easier if all data container classes would keep their properties in a name/value hash.

You're right, looking at the implementation of TPersistent and TComponent and comparing the overhead to simple data classes is on my list.

And of course I'm aware of the shallow copy vs. deep copy problem.

For records I am not sure, probably you should need a method on the container or check on some internal (compiler magic) functions such as CopyRecord and others.

Currently I'm dealing with records, so there is my first target.

I feared it would be that way. I think writing an extension for Lazarus and linking it into the "source" or "refactoring" menu will be a lot less work, I'll have a deeper look.

Hope that helps.

It does, thank you.

Show quoted text 29 lines
Chriss On Dec 27, 2014 6:22 PM, "Marc Santhoff" wrote: > On Sa, 2014-12-27 at 16:45 +0100, Bart wrote: > > On 12/27/14, Marc Santhoff wrote: > > > > > function clone(data_in: a_record): a_record; > > > var > > > data: Pa_record; > > > begin > > > new(data); > > data^ := data_in; //should work* > > > end; > > > > * Might not be a good idea if data contains a class(reference). > > Oops, I just typed that away and did not hit CTRL-F9 - which is useless > in the mailer anyway. ;) > > -- > Marc Santhoff > > _______________________________________________ > fpc-pascal maillist - > http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal > _______________________________________________ fpc-pascal maillist - http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Marc Santhoff

Reply by email

Chriss Kalogeropoulos
to Marc Santhoff

Hi again,

Sven made a good point on records. However most of the time it is easier to use classes.
Also you might be able to write some code to copy the property values using rtti so you can avoid the read/write component and the extra overhead. It will work for TPersistent descendants but might be tricky to cover all cases.

Your proposal on the name/value pair reminds me of Qt but in the Delphi/Fpc world it is done with rtti.

Chriss
Στις 28 Δεκ 2014 2:56 π.μ., ο χρήστης "Marc Santhoff" έγραψε:

Show quoted text 74 lines
On Sa, 2014-12-27 at 19:56 +0200, Chriss Kalogeropoulos wrote: > Hi, > > FPC does not support copy-construction so either you must override the > TPersistent.Assign method or in case of TComponent you can use > ReadComponent/WriteComponent. :| > You should also take into account deep vs swallow copy semantics as well as > the type of the container and contained classes > (TPersistent/TCmponent/TCollection descendant). TCollection is a good idea. Life could be easier if all data container classes would keep their properties in a name/value hash. You're right, looking at the implementation of TPersistent and TComponent and comparing the overhead to simple data classes is on my list. And of course I'm aware of the shallow copy vs. deep copy problem. > For records I am not sure, probably you should need a method on the > container or check on some internal (compiler magic) functions such as > CopyRecord and others. Currently I'm dealing with records, so there is my first target. I feared it would be that way. I think writing an extension for Lazarus and linking it into the "source" or "refactoring" menu will be a lot less work, I'll have a deeper look. > Hope that helps. It does, thank you. > Chriss > On Dec 27, 2014 6:22 PM, "Marc Santhoff" wrote: > > > On Sa, 2014-12-27 at 16:45 +0100, Bart wrote: > > > On 12/27/14, Marc Santhoff wrote: > > > > > > > function clone(data_in: a_record): a_record; > > > > var > > > > data: Pa_record; > > > > begin > > > > new(data); > > > data^ := data_in; //should work* > > > > end; > > > > > > * Might not be a good idea if data contains a class(reference). > > > > Oops, I just typed that away and did not hit CTRL-F9 - which is useless > > in the mailer anyway. ;) > > > > -- > > Marc Santhoff > > > > _______________________________________________ > > fpc-pascal maillist - > > http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal > > > _______________________________________________ > fpc-pascal maillist - > http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal -- Marc Santhoff _______________________________________________ fpc-pascal maillist - http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal

Reply by email

Marc Santhoff
to Sven Barth: Shouldn't the normal assignment be enough for any non-reference (aka non-managed…
Sven Barth wrote 6 lines
Am 27.12.2014 16:11 schrieb "Marc Santhoff" : > Is there any way of cloning record and objects having only data fields? > Or do I have to copy the (non reference) fields one by one as usual? Shouldn't the normal assignment be enough for any non-reference (aka non-managed pointers) fields?

In principle you are right, maybe too simple for me. ;)

To be serious I remember some problems in the past, IIRC there were strings involved, which are in fact pointers under the surface. I'll check that, having to dig deep ...

Meaning first you simply assign your input record to the result (strings, arrays and interfaces will be handled here) and then you update those fields that should be "deep copied".

Should do.

Marc Santhoff

Reply by email

Marc Santhoff
to Chriss Kalogeropoulos: Sven made a good point on records. However most of the time it is easier to use classes.…
Chriss Kalogeropoulos wrote
Hi again, Sven made a good point on records. However most of the time it is easier to

It took me some time to understand, he did actually.

use classes.

Not possible on old code, new stuff is using objects for sure.

Also you might be able to write some code to copy the property values using rtti so you can avoid the read/write component and the extra overhead. It will work for TPersistent descendants but might be tricky to cover all cases.

If the base class is or can be TPersistant that would work. I like the idea, having done sth. like it way back in the past when Delphi 1 (in words: one) was new. The documentation was kind of bad, sparse at least.

Your proposal on the name/value pair reminds me of Qt but in the Delphi/Fpc world it is done with rtti.

Interesting, if Qt really does it like that. Some code to stare at. :)

Marc Santhoff

Reply by email