Recent

Author Topic: How to declare such a record constant with variable length array....  (Read 2289 times)

chenyuchih

  • Jr. Member
  • **
  • Posts: 81
Hello,

I have a question about record type declaration. This record is used for my product machine and contains some performance test data. Each test data size is fixed but the data quantity of each machine might be different. The following is my thought and question:

Code: Pascal  [Select][+][-]
  1. Type
  2.   PerformanceData:Array[0..3] of Double;
  3.  
  4.   Machine:Record
  5.     Model:String;
  6.     Performance:Array of PerformanceData; //  <- Well, this line is wrong but I don't know how to correct it
  7.   end;
  8.  
  9. Const
  10.   AllMachine:Array[0..25] of Machine = (
  11.   (Model:'AAA';
  12.    Performance:(
  13.    (1,2,3,4),
  14.    (5,6,7,8),
  15.    .... // Maybe 10 test data
  16.   );
  17.  
  18.   (Model:'BBB';
  19.    Performance:(
  20.    (9,10,11,12),
  21.    (13,14,15,16),
  22.    .... // Maybe 12 test data
  23.    );
  24.   ),
  25.  
  26.   .....
  27.  
  28.   (Model:'ZZZ';
  29.    Performance:(
  30.    (1.2,3.4,5.6,7.8),
  31.    (9.10,11.12,13.14,15.16),
  32.    .... // Maybe 9 test data
  33.    );
  34.   )
  35.   );
  36.  

In short, what I want is a const record type that could have different length array. Currently I use strings to store all information then split, conversion them in program. But the string manipulation could be a speed bottleneck. Is there any suggestion for my need?

Thanks!

Chen, Yu-Chih(David Chen)

jamie

  • Hero Member
  • *****
  • Posts: 6090
Re: How to declare such a record constant with variable length array....
« Reply #1 on: December 15, 2018, 08:49:22 pm »
performance:performanceData;


it's customary to place "T" at the start of types

TPerformanceData;

By looking at your code I am sure you'll have more questions  :)

etc.

P.S.
  if that was meant to be a variable sized array, you need to set the length..
  Come back is so, we may need to change your code structure  :D

I think you want this as your type

TPerformanceData:Array of Array[0..3] of Double;

and in your record
 Performance :TPormanceData;

but you still need to set the size;

Scratch that, you are using constants, they need to be fixed lengths if that is the case.

create this dynamically and move values into them etc..

« Last Edit: December 15, 2018, 09:00:10 pm by jamie »
The only true wisdom is knowing you know nothing

Thaddy

  • Hero Member
  • *****
  • Posts: 14197
  • Probably until I exterminate Putin.
Re: How to declare such a record constant with variable length array....
« Reply #2 on: December 15, 2018, 09:10:39 pm »
( @jamie: I found this quite obvious. It is useful to store reference performance for a machine to compare to actual measurements of a production item. )
You mean like this?
Code: Pascal  [Select][+][-]
  1. {$mode objfpc}
  2. Type
  3.   TPerformanceData = specialize TArray<Double>;
  4.  
  5.   Machine = Record
  6.     Model:String;
  7.     Performance:specialize TArray<TPerformanceData>;
  8.   end;
  9.  
  10. const
  11.   AllMachines:specialize TArray<Machine> = (
  12.   (Model:'AAA';
  13.    Performance:(
  14.    (1,2,3,4),
  15.    (5,6,7,8)
  16.    )
  17.   ),
  18.   (Model:'BBB';
  19.    Performance:(
  20.    (1,2,3,4),
  21.    (5,6,7,8),
  22.    (9,10,11,12),
  23.    (13,14,15,16)
  24.    );
  25.   ),
  26.   (Model:'ZZZ';
  27.    Performance:(
  28.    (1.2,3.4,5.6,7.8),
  29.    (9.10,11.12,13.14,15.16)
  30.    );
  31.   )
  32.   );
  33.  
  34. begin
  35.   writeln(AllMachines[0].Model);
  36. end.

Needs fpc3.2 or trunk, though...

But it allows for "ragged"  arrays too!! the array consts are flexiible in all dimensions
E.g. Try adding the following:
Code: Pascal  [Select][+][-]
  1.   (Model:'T-ford';
  2.    Performance:(
  3.    (1.2,3.4,5.6,7.8,7.9,5,0,1),
  4.    (9.10,11.12,13.14,15.16).
  5.    (3,2,1);
  6.    );
  7.   );

You should use for in do to read the elements of the array constants. Mind you they ARE constants as you declared them but the code for variables is not much different.....:
 8-) change const to var! 8-) O:-)..
Loop the structure - const or var - like so:
Code: Pascal  [Select][+][-]
  1. var
  2.   m:machine;  
  3.   p:TPerformanceData;
  4.   d:double;
  5. begin
  6.   for m in allmachines do
  7.     begin
  8.       writeln(m.Model);
  9.       for p in m.Performance do
  10.       begin
  11.         for d in p do write(d:3:2,' ');
  12.         writeln;
  13.       end;
  14.      writeln;
  15.     end;  
  16. end.

« Last Edit: December 15, 2018, 10:58:54 pm by Thaddy »
Specialize a type, not a var.

chenyuchih

  • Jr. Member
  • **
  • Posts: 81
Re: How to declare such a record constant with variable length array....
« Reply #3 on: December 16, 2018, 08:01:25 am »
@jamie: I ever thought of using dynamic array variable instead of constant. But it's too inconvenient to fill all data to the array elements in code. BTW, external data file(ini or database) is not preferred in case of missing file errors. That's why I have such a strange question.

@Thaddy: It seems that your first proposal is close what I need. Can I just declare

TPerformanceData = Array[0..3] of Double;

and use

specialize TArray<TPerformanceData>

in record? Thus I can avoid ragged array problem you mentioned.

Well....does your suggestion can only be used in fpc 3.2 or trunk? If it is not supported and no alternative way in the current stable version(3.0.4), I have to wait for next release of FPC.

Anyway, I appreciate for all your reply. Thanks!

Chen, Yu-Chih(David Chen)

Thaddy

  • Hero Member
  • *****
  • Posts: 14197
  • Probably until I exterminate Putin.
Re: How to declare such a record constant with variable length array....
« Reply #4 on: December 16, 2018, 09:04:05 am »
Yes, you can simply do
Code: Pascal  [Select][+][-]
  1. TPerformanceData = Array[0..3] of Double;
  2. //and use
  3. specialize TArray<TPerformanceData>
  4.  
The rest of the code can stay the same.

Yes, you need 3.2.0 for this because of several enhancements and bug fixes over 3.0.4 that directly affect my example code.
3.2.0. is very stable, feature complete, in RC phase and imho ready for use in some production applications.
Also note I did not use other units at all: everything is in system....
Second note: ragged arrays are a feature and not a problem!!! and only possible with dynamic arrays.
Static arrays are always rectangular.

And finally: if you need to change from const to var replace just that one const with var and you have something close to Jamie's suggestion...even more flexible.

For completeness your intention using my code:
Code: Pascal  [Select][+][-]
  1. program perfdata;
  2. {$ifdef mswindows}{$apptype console}{$endif}{$mode objfpc}
  3. Type
  4.   TPerformanceData = Array[0..3] of Double;
  5.  
  6.   TMachine = Record
  7.     Model:String;
  8.     Performance:specialize TArray<TPerformanceData>;
  9.   end;
  10.  
  11. const // or var ...
  12.   AllMachines:specialize TArray<TMachine> = (
  13.   (Model:'AAA';
  14.    Performance:(
  15.    (1,2,3,4),
  16.    (5,6,7,8)
  17.    )
  18.   ),
  19.   (Model:'BBB';
  20.    Performance:(
  21.    (1,2,3,4),
  22.    (5,6,7,8),
  23.    (9,10,11,12),
  24.    (13,14,15,16)
  25.  
  26.    );
  27.   ),
  28.   (Model:'ZZZ';
  29.    Performance:(
  30.    (1.2,3.4,5.6,7.8),
  31.    (9.10,11.12,13.14,15.16)
  32.    );
  33.   )  
  34. );
  35. // test and dump the matrices.
  36. var
  37.   m:TMachine;  
  38.   p:TPerformanceData;
  39.   d:double;
  40. begin
  41.   for m in allmachines do
  42.     begin
  43.       writeln(m.Model);
  44.       for p in m.Performance do
  45.       begin
  46.         for d in p do write(d:3:2,' ');
  47.         writeln;
  48.       end;
  49.       writeln;
  50.     end;  
  51. end.
As you can see the code is brief and quite elegant.
« Last Edit: December 16, 2018, 11:19:51 am by Thaddy »
Specialize a type, not a var.

chenyuchih

  • Jr. Member
  • **
  • Posts: 81
Re: How to declare such a record constant with variable length array....
« Reply #5 on: December 16, 2018, 01:13:41 pm »
During thinking how to solve my issue, I feel that string in pascal is so magical because it allows arbitrary  length (of course not exceed pointer limit) chars sequence(just like dynamic array but without setlength), the memory can be managed automatically, declared as var or constant with content.

Originally I guessed that I just need a similar type with float point numbers and never thought it needs such a advanced feature. Now I know that things may not be as simple as it looks like.

Thank you for your suggestion and explanation!

David

 

TinyPortal © 2005-2018