Recent

Author Topic: Use Array of Const in a variable  (Read 4329 times)

jollytall

  • Sr. Member
  • ****
  • Posts: 377
Use Array of Const in a variable
« on: January 24, 2023, 11:00:05 am »
For my other problem (https://forum.lazarus.freepascal.org/index.php/topic,61956.0.html) the solution might be in using an array of const parameter for a routine. In that case an array of mixed type can be passed on. The problem is how to pass on an array (of any type) that is built up in a variable (not on the fly). In the following example:
Code: Pascal  [Select][+][-]
  1. program simple;
  2.  
  3. uses
  4. SysUtils;
  5.  
  6. type
  7.   tConstArray  = array of const; // ERROR
  8.  
  9. procedure a(const x: array of const);
  10.   begin
  11.   writeln('OK');
  12.   end;
  13. procedure b1;
  14.   begin
  15.   a(['abc', 456, 78.9]);
  16.   end;
  17. procedure b2;
  18.   var
  19.     ConstArray: array of const; // ERROR
  20.   begin
  21.   SetLength(ConstArray, 0);
  22.   a(ConstArray); // ERROR - Expects array of const
  23.   end;
  24. procedure b3;
  25.   var
  26.     ConstArray: array of variant;
  27.   begin
  28.   SetLength(ConstArray, 0);
  29.   a(ConstArray); // ERROR - Expects array of const
  30.   end;
  31. procedure b4(y: array of const);
  32.   begin
  33.   SetLength(y,0); // ERROR - Type mismatch
  34.   a(y);
  35.   end;
  36. procedure b5(const y: array of const);
  37.   begin
  38.   SetLength(y,0); // ERROR - Type mismatch
  39.   a(y);
  40.   end;
  41. procedure b6(y: array of const);
  42.   var
  43.     s: string;
  44.   begin
  45.   if length(y) > 0 then
  46.     begin
  47.     s := 'abc';
  48.     y[0].vAnsistring := @s;
  49.     a(y);
  50.     end;
  51.   end;
  52.  
  53. begin
  54. b6([12]); // This one works, event when the type of the special variant record changes in b6
  55. Sleep(500);
  56. end.

no new type tConstArray can be constructed nor globally (row 7), neither locally (b2), only in the parameter list of a routine (b4 - b6). Even for a parameter like variable, the length cannot be changed (b4-b5), however elements can be changed even to a different type (b6). I could not pass-on any other type of array either, as it gives a type mismatch (b3).
Is there any solution, or array of const can only be used for arrays generated from its element when calling a routine?

KodeZwerg

  • Hero Member
  • *****
  • Posts: 2269
  • Fifty shades of code.
    • Delphi & FreePascal
Re: Use Array of Const in a variable
« Reply #1 on: January 24, 2023, 11:12:13 am »
I suggest you take a look into the "Format()" method.
That is able to take anything as input "%s %i, ['string', 123]"
Build your array like that and have just one method to gather your wanted information out of input.
« Last Edit: Tomorrow at 31:76:97 xm by KodeZwerg »

TRon

  • Hero Member
  • *****
  • Posts: 4377
Re: Use Array of Const in a variable
« Reply #2 on: January 24, 2023, 11:19:53 am »
You mean something like this ?
Code: Pascal  [Select][+][-]
  1.  
  2. procedure a(const x: array of const);
  3. begin
  4.  writeln('OK');
  5. end;
  6.  
  7. var
  8.   k: string;
  9.   l: boolean;
  10.   m: pointer;
  11. begin
  12.   k := 'hello';
  13.   l := true;
  14.   m := nil;
  15.   a([k,l,m]);
  16. end.

Or in case you wish to make it explicit then you can use an array of TVarRec.
« Last Edit: January 24, 2023, 11:21:53 am by TRon »
Today is tomorrow's yesterday.

Stefan Glienke

  • New Member
  • *
  • Posts: 24
Re: Use Array of Const in a variable
« Reply #3 on: January 24, 2023, 11:21:57 am »
An array of const parameter is implemented as an array of TVarRec under the hood.

TRon

  • Hero Member
  • *****
  • Posts: 4377
Re: Use Array of Const in a variable
« Reply #4 on: January 24, 2023, 11:28:29 am »
As indicated by Stefan.
Code: Pascal  [Select][+][-]
  1. program test;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. type
  6.   tConstArray  = array of TVarRec;
  7.  
  8. procedure a(const x: array of const);
  9. begin
  10.  writeln('OK');
  11. end;
  12.  
  13. var
  14.   x: TConstArray;
  15.   y: TConstArray =
  16.   (
  17.     (vtype : vtChar;    vchar : '1'),
  18.     (vtype : vtInteger; vinteger : 1),
  19.     (vtype : vtPointer; vpointer : nil)
  20.   );
  21.  
  22. begin
  23.   setlength(x, 1);
  24.   x[0].vtype := vtChar;
  25.   x[0].vchar := '1';
  26.   a(x);
  27.   a(y);
  28. end.
  29.  
Today is tomorrow's yesterday.

Zvoni

  • Hero Member
  • *****
  • Posts: 3260
Re: Use Array of Const in a variable
« Reply #5 on: January 24, 2023, 11:28:31 am »
no new type tConstArray can be constructed nor globally (row 7), neither locally (b2), only in the parameter list of a routine (b4 - b6). Even for a parameter like variable, the length cannot be changed (b4-b5), however elements can be changed even to a different type (b6). I could not pass-on any other type of array either, as it gives a type mismatch (b3).
Is there any solution, or array of const can only be used for arrays generated from its element when calling a routine?
As far as i understand it:
1) Array Of Const can only (!!) be used in a Function-Signature (kinda for "variable amount" of Arguments).
You cannot "create" your own Type from it (e.g. Type TIntArray = Array Of Integer;)
2) You cannot pass an array itself to it. You have to pass "individual" values in Array-Notation.
Exception (like Tron pointed out): Array of TVarRec (but not tested by myself)
One System to rule them all, One Code to find them,
One IDE to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------
Code is like a joke: If you have to explain it, it's bad

KodeZwerg

  • Hero Member
  • *****
  • Posts: 2269
  • Fifty shades of code.
    • Delphi & FreePascal
Re: Use Array of Const in a variable
« Reply #6 on: January 24, 2023, 11:34:08 am »
You mean something like this ?
Or in case you wish to make it explicit then you can use an array of TVarRec.
Yes, but I liked that he learn by study sources of Format  :-*
« Last Edit: Tomorrow at 31:76:97 xm by KodeZwerg »

TRon

  • Hero Member
  • *****
  • Posts: 4377
Re: Use Array of Const in a variable
« Reply #7 on: January 24, 2023, 11:40:23 am »
Yes, but I liked that he learn by study sources of Format  :-*
I understand but in the other thread I'd already pointed TS to https://www.freepascal.org/docs-html/ref/refsu69.html so that means there is hardly any magic left....

Also why I do not fully understood why the question. TS seems to be experimenting with some of the inner workings wrt FPC probably (guessing) to find the holy grail of passing a variable amount of different types to a function (in a manageable way). Alas there simply is none. Array of const comes close but it is still a pita. Maybe extended rtti will be able to help out there (in future).

But being persistent proofs fruitful (like finding bugs) so credit where credit is due.
« Last Edit: January 24, 2023, 11:49:11 am by TRon »
Today is tomorrow's yesterday.

KodeZwerg

  • Hero Member
  • *****
  • Posts: 2269
  • Fifty shades of code.
    • Delphi & FreePascal
Re: Use Array of Const in a variable
« Reply #8 on: January 24, 2023, 11:49:57 am »
Yes, but I liked that he learn by study sources of Format  :-*
I understand but in the other thread I'd already pointed TS to https://www.freepascal.org/docs-html/ref/refsu69.html so that means there is hardly any magic left.... Also why I do not fully understood why the question. TS seems to be experimenting with some of the inner workings wrt FPC probably (guessing) to find the holy grail of passing a variable amount of different types to a function (in a manageable way). Alas there simply is none. Array of const comes close but it is still a pita. Maybe extended rtti will be able to help out there (in future).

I am glad that early on I've learned about taglists. Also a pita but imho more manageable.
Ahh I am sorry, I did not read other thread and your link is perfect, no questions should be left. I am sorry for being lazy  :D and not read all-everywhere
« Last Edit: Tomorrow at 31:76:97 xm by KodeZwerg »

TRon

  • Hero Member
  • *****
  • Posts: 4377
Re: Use Array of Const in a variable
« Reply #9 on: January 24, 2023, 11:52:23 am »
@KodeZwerg:
No need to be sorry about anything. I fully understand that not everyone is as mat as this hatter keeping up because of sleep related issues  :)
Today is tomorrow's yesterday.

jollytall

  • Sr. Member
  • ****
  • Posts: 377
Re: Use Array of Const in a variable
« Reply #10 on: January 24, 2023, 11:59:17 am »
Thanks,

I suggest you take a look into the "Format()" method.

I am not sure, how you mean to  make it work? Also to format, you need the individual values. Here the whole point was to have it in a variable.
You mean something like this ?
...
Or in case you wish to make it explicit then you can use an array of TVarRec.
No, your code also assumes that you know at compile time the number of elements. The whole point is to build up an array at run-time and then pass that array in one.
Yes, tVarRec does the trick. I was close to it, just tried to use array of Variant and not array of tVarRec.

An array of const parameter is implemented as an array of TVarRec under the hood.
Then these two should be identical, shouldn't?
Code: Pascal  [Select][+][-]
  1. procedure a(x : array of const);
  2. procedure b(x: array of tVarRec);
  3.  
Still
a(['123']); works, but
b(['123']); is a compile error.

As indicated by Stefan.
Code: Pascal  [Select][+][-]
  1. program test;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. type
  6.   tConstArray  = array of TVarRec;
  7.  
  8. procedure a(const x: array of const);
  9. begin
  10.  writeln('OK');
  11. end;
  12.  
  13. var
  14.   x: TConstArray;
  15.   y: TConstArray =
  16.   (
  17.     (vtype : vtChar;    vchar : '1'),
  18.     (vtype : vtInteger; vinteger : 1),
  19.     (vtype : vtPointer; vpointer : nil)
  20.   );
  21.  
  22. begin
  23.   setlength(x, 1);
  24.   x[0].vtype := vtChar;
  25.   x[0].vchar := '1';
  26.   a(x);
  27.   a(y);
  28. end.
  29.  
[/code]
How do I add AnsiString and read it back?

Yes, but I liked that he learn by study sources of Format  :-*
:D :D

KodeZwerg

  • Hero Member
  • *****
  • Posts: 2269
  • Fifty shades of code.
    • Delphi & FreePascal
« Last Edit: Tomorrow at 31:76:97 xm by KodeZwerg »

jollytall

  • Sr. Member
  • ****
  • Posts: 377
Re: Use Array of Const in a variable
« Reply #12 on: January 24, 2023, 12:27:03 pm »
Oh, just if someone is really interested why I am struggling with this question: (It is a bit OffTopic to this questions, but someone might be interester).

In Tensorflow in a Graph there are Operations. Before adding an Operation to a Graph, it has to be built. Building an Operation is a long process (like over 100 source code lines). There are over 1300 individual operations. Every operation can have (or can be missing) various number of inputs, input arrays (called input lists) and outputs (and also output lists and attributes, but I do not want to over complicate). Imagine abs(), what has 1 input and 1 output, but matrix multiplication has 2 inputs and 1 output, or concatenate has no input but 1 input array (a list of n number of individual tensors to be merged) and 1 output, and so on.
If one wants a general purpose Operation creation routine, it has to take the parameters in an array, as no fixed number of parameters can be known in advance.
In the earlier version I had three parameters (again, in reality it was even more), one array of inputs, one array of input lists and one array of outputs. Then inside, when building the Operation, I first added the inputs then the input lists and finally the outputs. Unfortunately the sequence of parameters must match with the sequence in the declaration, but luckily earlier the individual inputs were all before the input lists and those before the outputs, so it was OK that first I iterated through the input array then the inputlist array and then the output array.
In the latest release there is (at least) one Operation, where the inputlist parameter is mixed among the input parameters. Hence my program fails in this particular case. Hence I need a new release where I can give the input and input list parameters mixed. They have different types, so if I can/could pass an array of mixed types and then iterate through them, figure out which is what type and add them sequentially with the right method that would be the desired outcome.
Sometimes humans (writing programs) call this routine, so they can just call it likes AddOperation([aninput, aninpulist, anotherinput, anoutput]);, but I also have simplified versions, where I want to pass on these parameters already received in an array.
Of course I am thinking of other solutions, like keeping separate input and inputlist arrays and adding a third array mapping what sequence to mixed them in and other creative solutions, but still trying to keep it relatively simple.

Hope it clarifies...

Stefan Glienke

  • New Member
  • *
  • Posts: 24
Re: Use Array of Const in a variable
« Reply #13 on: January 24, 2023, 12:39:17 pm »
An array of const parameter is implemented as an array of TVarRec under the hood.
Then these two should be identical, shouldn't?
Code: Pascal  [Select][+][-]
  1. procedure a(x : array of const);
  2. procedure b(x: array of tVarRec);
  3.  
Still
a(['123']); works, but
b(['123']); is a compile error.

array of const has compiler support that generates code to stuff your arguments into an array of TVarRec, the array of TVarRec does not have that compiler support.

Depending on the types you want to support I would consider using an array of Variant - or in Delphi I would probably use an array of TValue - I don't know how far the development of System.Rtti is in the FPC RTL. With certain values you have to be careful in an array of const/TVarRec because they are just passed by ref (such as a string) and thus after the call has finished the reference might be invalid so you cannot simply take the array of TVarRec and store it somewhere for later use - because if you access say VAnsiString or VUnicodeString that reference could very well be a dangling reference.
« Last Edit: January 24, 2023, 12:46:21 pm by Stefan Glienke »

jollytall

  • Sr. Member
  • ****
  • Posts: 377
Re: Use Array of Const in a variable
« Reply #14 on: January 24, 2023, 12:46:13 pm »
How do I add AnsiString and read it back?
By opening this Link
https://www.freepascal.org/docs-html/ref/refsu69.html
and read.

And where in this document shall I find how to write an AnsiString into a variable of tVarRec type? I could only write this one (what compiles), but this does not work:

Code: Pascal  [Select][+][-]
  1. program simple;
  2. uses
  3.  SysUtils;
  4.  
  5. var
  6.   s: string;
  7.   V: tVarRec;
  8.  
  9. begin
  10.  s := 'abc';
  11.  V.VAnsiString := @s;
  12.  writeln('Read back: ',AnsiString(V.VAnsiString));
  13.  Sleep(500);
  14.  end.    

and even if it would work, it would mean to use a temporary s variable.

 

TinyPortal © 2005-2018