Recent

Author Topic: Using dynamic array constructors  (Read 8264 times)

howardpc

  • Hero Member
  • *****
  • Posts: 3181
Using dynamic array constructors
« on: July 03, 2016, 04:29:17 pm »
The introduction of a Delphi-compatible class-like constructor syntax in FPC 3.0.0
   http://wiki.freepascal.org/FPC_New_Features_3.0#Dynamic_array_constructors
is very welcome.

Is it possible to pass values to such a constructor dynamically (i.e. not by typing literal values and commas into a source code editor)?

Leledumbo

  • Hero Member
  • *****
  • Posts: 8112
  • Programming + Glam Metal + Tae Kwon Do = Me
Re: Using dynamic array constructors
« Reply #1 on: July 03, 2016, 05:17:21 pm »
Do you have any example wish of how it should be done? i.e.: an uncertain-to-work code you would like to type. Probably you just need System.Copy.

Thaddy

  • Hero Member
  • *****
  • Posts: 9187
Re: Using dynamic array constructors
« Reply #2 on: July 03, 2016, 05:29:16 pm »
Urhm. Asking about scripting language features?

But anyway. Do you have an example in a comparable language like C or C++?
Or some pseudo code of what you envisage?
also related to equus asinus.

howardpc

  • Hero Member
  • *****
  • Posts: 3181
Re: Using dynamic array constructors
« Reply #3 on: July 03, 2016, 08:24:28 pm »
I was looking for something that would interpret a comma-separated list as a list of successive values in the array to be initialized. Perhaps the following short example explains what I am after:

Code: Pascal  [Select]
  1. program Project1;
  2.  
  3. {$H+}
  4.  
  5. type
  6.   TStringDynArray = array of ansistring;
  7.  
  8. const
  9.   NumberStr = 'zero,one,two,three,four,five,six,seven';
  10.  
  11. var
  12.   nums: TStringDynArray;
  13.   idx: integer = 0;
  14.   s: ansistring;
  15. begin
  16.   // initialize array
  17.   nums:=TStringDynArray.create(NumberStr);
  18.   // display array value(s)
  19.   for s in nums do begin
  20.     WriteLn('Index:',idx,' ',s);
  21.     Inc(idx);
  22.   end;
  23. end.

Compare this with the constructor
Code: Pascal  [Select]
  1. nums:=TStringDynArray.create('zero','one','two','three','four','five','six','seven');
« Last Edit: July 03, 2016, 08:29:20 pm by howardpc »

Bart

  • Hero Member
  • *****
  • Posts: 3540
    • Bart en Mariska's Webstek
Re: Using dynamic array constructors
« Reply #4 on: July 03, 2016, 08:38:26 pm »
How can the compiler ever know what you mean then?
Should it treat numberstring as one string (why should not the array of strig contain a stringwith a comma), or as a commaseparated list?

Bart

molly

  • Hero Member
  • *****
  • Posts: 2345
Re: Using dynamic array constructors
« Reply #5 on: July 03, 2016, 09:48:14 pm »
You are absolutely right there Bart but, in the quest to instruct the compiler to be able to do the right thing there:
Code: [Select]
const
  NumberStrings = 'one', 'two';

Which produces a:
Quote
Fatal: Syntax error, ";" expected but "," found

or perhaps more accurate:
Code: [Select]
const
  NumberStrings = ('one', 'two');

Which produces a:
Quote
Fatal: Syntax error, ")" expected but "," found


The way it's currently suppose to be:
Code: [Select]
Const
  NumConst : Array[0..1] of ansistring = ('zero','one');
or:
Code: [Select]
Var
  NumVar   : array[0..1] of ansistring = ('zero','one');

Maybe that is what howardpc (in basics) is/was referring to ?
« Last Edit: July 03, 2016, 10:00:12 pm by molly »

molly

  • Hero Member
  • *****
  • Posts: 2345
Re: Using dynamic array constructors
« Reply #6 on: July 03, 2016, 10:52:28 pm »
Nevermind. Something like this seems to do what was asked for:
Code: Pascal  [Select]
  1. program arrayhelper;
  2.  
  3. {$MODE OBJFPC}{$MODESWITCH TYPEHELPERS}
  4.  
  5. Uses
  6.   StrUtils;
  7.  
  8. type
  9.   TStringDynArray = array of ansistring;
  10.  
  11. type
  12.   TStringDynArrayHelper = type helper for TStringDynArray
  13.     class function CreateFromDelimitedString(DelimString: String): TStringDynArray static;
  14.   end;
  15.  
  16. class function TStringDynArrayHelper.CreateFromDelimitedString(DelimString: String): TStringDynArray;
  17. var
  18.   num, i : Integer;
  19. begin
  20.   num := WordCount(DelimString, [',']);
  21.   SetLength(Result, num);
  22.   for i := 1 to num do
  23.   begin
  24.     Result[i-1] := ExtractWord(i, DelimString, [',']);
  25.   end;
  26. end;
  27.  
  28. const
  29.   NumberStr = 'zero,one,two,three,four,five,six,seven';
  30. var
  31.   nums  : TStringDynArray;
  32.   idx   : integer = 0;
  33.   s     : ansistring;
  34. begin
  35.   // initialize array
  36. //  nums:=TStringDynArray.create(NumberStr);
  37.   nums:=TStringDynArray.CreateFromDelimitedString(NumberStr);
  38.  
  39.   // display array value(s)
  40.   for s in nums do begin
  41.     WriteLn('Index:',idx,' ',s);
  42.     Inc(idx);
  43.   end;
  44. end.
  45.  

ArtLogi

  • Full Member
  • ***
  • Posts: 144
Re: Using dynamic array constructors
« Reply #7 on: July 03, 2016, 11:14:28 pm »
Molly how you can do the word extracting without passing the character beforehand in the variable of the type of TSysCharSet? Is the key those square brackets? I did fight "days" before getting it right in FPC2.6.xx :o

molly

  • Hero Member
  • *****
  • Posts: 2345
Re: Using dynamic array constructors
« Reply #8 on: July 03, 2016, 11:33:08 pm »
Molly how you can do the word extracting without passing the character beforehand in the variable of the type of TSysCharSet? Is the key those square brackets? I did fight "days" before getting it right in FPC2.6.xx :o
Well, it is working for me since i can remember (but, i have bad memory  :D).

Maybe this will be able to help you ?
Code: [Select]
program passer;

{$MODE OBJFPC}{$H+}
Uses
  SysUtils, StrUtils;

Const
  LowChars  = ['a'..'z'];

var
  HighChars : TSysCharset = ['A'..'Z'];

  num       : integer;
  S         : String;

begin
  S := 'I stand amid the roar of a surf-tormented shore, and 1 hold within my hand Grains of the golden sand';
  num := wordcount(S, []);
  Writeln('num 0 = ', num);

  num := wordcount(S, LowChars);
  Writeln('num 1 = ', num);

  num := wordcount(S, HighChars);
  Writeln('num 2 = ', num);

  HighChars := ['a','b',','];
  num := wordcount(S, HighChars);
  Writeln('num 3 = ', num);

  include(highChars, ' ');
  num := wordcount(S, HighChars);
  Writeln('num 4 = ', num);
 
  HighChars := HighChars + ['1','2'];
  num := wordcount(S, HighChars);
  Writeln('num 5 = ', num);
end.

Also have a look at set operators.
« Last Edit: July 03, 2016, 11:37:53 pm by molly »

howardpc

  • Hero Member
  • *****
  • Posts: 3181
Re: Using dynamic array constructors
« Reply #9 on: July 03, 2016, 11:39:22 pm »
Many thanks, molly.
I prefer a helper with no dependency on StrUtils.

Code: Pascal  [Select]
  1. TStringDynArrayHelper = type helper for TStringDynArray
  2.     class function CreateCommaDelimited(const aCommaString: string): TStringDynArray; static;
  3.   end;
  4.  
  5. class function TStringDynArrayHelper.CreateCommaDelimited(const aCommaString: string): TStringDynArray;
  6. var
  7.   p: integer = 1;
  8.   len: integer = 0;
  9.   predLen: integer;
  10.   s: string;
  11. begin
  12.   if (aCommaString = '') then
  13.     Exit(nil);
  14.   repeat
  15.     s:='';
  16.     while (p <= Length(aCommaString)) and (aCommaString[p] <> ',') do begin
  17.       s:=s + aCommaString[p];
  18.       Inc(p);
  19.     end;
  20.     predLen:=len;
  21.     Inc(len);
  22.     SetLength(Result, len);
  23.     Result[predLen]:=s;
  24.     Inc(p);
  25.   until (p > Length(aCommaString));
  26. end;
« Last Edit: July 04, 2016, 12:52:49 am by howardpc »

molly

  • Hero Member
  • *****
  • Posts: 2345
Re: Using dynamic array constructors
« Reply #10 on: July 04, 2016, 01:19:30 am »
I prefer a helper with no dependency on StrUtils.
Ah, indeed. i was being lazy   ;D

As a matter of fact so lazy that i don't even wanted to use a type helper  :D
Code: Pascal  [Select]
  1. program arraymore;
  2.  
  3. {$MODE OBJFPC}
  4.  
  5. {.$DEFINE USETYPEHELPERS}
  6. {$IFDEF USETYPEHELPERS}
  7.   {$MODESWITCH TYPEHELPERS}
  8. {$ENDIF}
  9.  
  10. Uses
  11.   Heaptrc, StrUtils;
  12.  
  13. type
  14.   TStringDynArray = array of ansistring;
  15.  
  16. {$IFDEF USETYPEHELPERS}
  17.  
  18. type
  19.   TStringDynArrayHelper = type helper for TStringDynArray
  20.     class function CreateFromDelimitedString(DelimString: String): TStringDynArray static;
  21.   end;
  22.  
  23. class function TStringDynArrayHelper.CreateFromDelimitedString(DelimString: String): TStringDynArray;
  24. var
  25.   num, i : Integer;
  26. begin
  27.   num := WordCount(DelimString, [',']);
  28.   SetLength(Result, num);
  29.   for i := 1 to num do
  30.   begin
  31.     Result[i-1] := ExtractWord(i, DelimString, [',']);
  32.   end;
  33. end;
  34.  
  35. operator := (S : string): TStringDynArray;
  36. begin
  37.   Result := TStringDynArray.CreateFromDelimitedString(S);
  38. end;
  39.  
  40. {$ELSE}
  41.  
  42. operator := (S : string): TStringDynArray;
  43. var
  44.   num, i : Integer;
  45. begin
  46.   num := WordCount(S, [',']);
  47.   SetLength(Result, num);
  48.   for i := 1 to num do
  49.   begin
  50.     Result[i-1] := ExtractWord(i, S, [',']);
  51.   end;
  52. end;
  53.  
  54. {$ENDIF}
  55.  
  56.  
  57. const
  58.   NumberStr = 'zero,one,two,three,four,five,six,seven';
  59. var
  60.   nums  : TStringDynArray;
  61.   idx   : integer = 0;
  62.   s     : ansistring;
  63. begin
  64.   // initialize array
  65. //  nums:=TStringDynArray.create(NumberStr);
  66. //  nums:=TStringDynArray.CreateFromDelimitedString(NumberStr);
  67.  
  68.   nums := NumberStr;
  69.  
  70.   // display array value(s)
  71.   for s in nums do begin
  72.     WriteLn('Index:',idx,' ',s);
  73.     Inc(idx);
  74.   end;
  75. end.
  76.  

Mind-boggling in case you use these kind of things to much/deep.

Edit:
Hmz, seems i misunderstood something ?:
Code: [Select]
const
  NumberStr = 'zero,one,two,three,four,five,six,seven';
var
  nums  : TStringDynArray = NumberStr;
produces:
Quote
  Fatal: Syntax error, "NIL" expected but "identifier NUMBERSTR" found
Is that not considered an assignment ? In which case it should be covered by the explicit assignment operator ? If not the case, is there a separate operator for such assignments ? (i was unable to find in the docs)
« Last Edit: July 04, 2016, 02:40:55 am by molly »

howardpc

  • Hero Member
  • *****
  • Posts: 3181
Re: Using dynamic array constructors
« Reply #11 on: July 04, 2016, 08:44:55 am »
Well
Code: Pascal  [Select]
  1. nums: TStringDynArray = NumberString;
is of course an assignment combined with a declaration.

However it does not use the ':=' operator you have defined, so the compiler rightly complains that the two types are incompatible.

BTW, do you know if recent Delphis now allow that C-style initialization syntax in the declaration of variables?

molly

  • Hero Member
  • *****
  • Posts: 2345
Re: Using dynamic array constructors
« Reply #12 on: July 04, 2016, 09:07:03 am »
BTW, do you know if recent Delphis now allow that C-style initialization syntax in the declaration of variables?
I have honestly no idea (we haven't used Delphi in ages).

But, i fully understand the desire to have such support. In fact i would already settle for getting rid of the requirement to declare the size of the array for a variable/constant. e.g. var x: TStringDynArray = ('One','Two');.

TBH, for me the desire comes from porting c-code. so for me .. uh .. it's about laziness  :D

ArtLogi

  • Full Member
  • ***
  • Posts: 144
Re: Using dynamic array constructors
« Reply #13 on: July 28, 2016, 07:25:33 pm »
It's allways the laziness  :D

Thaddy

  • Hero Member
  • *****
  • Posts: 9187
Re: Using dynamic array constructors
« Reply #14 on: July 28, 2016, 07:47:09 pm »
BTW, do you know if recent Delphis now allow that C-style initialization syntax in the declaration of variables?

If you mean:
Code: Pascal  [Select]
  1. program a;
  2. {$IFDEF FPC}{$MODE DELPHI}{$ENDIF}
  3. {$APPTYPE CONSOLE}
  4. var a:integer = 1;
  5. begin
  6.   ..do something with a
  7. end.
  8.  
The answer is yes...

If you mean:
Code: Pascal  [Select]
  1. program b;
  2. {$IFDEF FPC}{$MODE DELPHI}{$ENDIF}
  3. {$APPTYPE CONSOLE}
  4. begin
  5.  with var a =1 do //declarations on the fly  
  6.  begin
  7.    inc(a);
  8.  end;
  9. end.
  10.  
The answer is no, and I hope that never happens... as a language construct: You will loose structure and oversight and your code becomes hard to read for mere mortals.
Note the Delphi IDE has some support for things like that, but that is not a language feature, but a refactoring/codecompletion feature of the IDE.
« Last Edit: July 28, 2016, 07:58:04 pm by Thaddy »
also related to equus asinus.