21

I want to do something like in PHP, Python and most other programming languages:

my_array_name = [128, 38459, 438, 23674...] 

So I tried to replicate this in Delphi/Pascal the best I could:

HSVtoRGB := [0, 0, 0];

(this is for a function which returns an RGB array given HSV values.)

But I am getting errors:

[DCC Error] Unit2.pas(44): E2001 Ordinal type required
[DCC Error] Unit2.pas(45): E2010 Incompatible types: 'HSVRealArray' and 'Set'

Any idea? This is school work - but my teacher didn't know the answer.

Thomas O
  • 6,026
  • 12
  • 42
  • 60

9 Answers9

23

When it comes to dynamic arrays, yes:

type
  TIntArray = array of integer;

procedure TForm1.Button1Click(Sender: TObject);
var
  MyArr: TIntArray;
begin
  MyArr := TIntArray.Create(10, 20, 30, 40);
end;

When it comes to static arrays, you need to write a helper function:

type
  TIntArray = array[0..2] of integer;

function IntArray(const A, B, C: integer): TIntArray;
begin
  result[0] := A;
  result[1] := B;
  result[2] := C;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  MyArr: TIntArray;
begin
  MyArr := IntArray(10, 20, 30);
end;

This resembles how the Point function creates a TPoint record. (Records and arrays are not the same thing, though.)

Andreas Rejbrand
  • 105,602
  • 8
  • 282
  • 384
  • Thanks for the suggestion, but it didn't work. My type is defined as `HSVRealArray = array[1..3] of real`, then I am trying to do this: `HSVtoRGB := HSVRealArray.Create(0, 0, 0)` but getting this: `[DCC Error] Unit2.pas(45): E2018 Record, object or class type required`. Any idea? – Thomas O Jun 27 '11 at 13:43
  • @Thomas O: That is not a dynamic array. That is a static array. – Andreas Rejbrand Jun 27 '11 at 13:44
  • @Andreas Oh okay... My error. `array of integer` looks like English not Delphi. Fixed, thanks. – Thomas O Jun 27 '11 at 13:45
  • 1
    +1 For the static array solution, it could also be an open array parameter. – Andriy M Jun 27 '11 at 14:18
  • @Andriy Open array wouldn't be much use since that would allow you to pass the wrong number of parameters. – David Heffernan Jun 27 '11 at 14:53
  • 1
    @David: Depending on the situation, excess elements could simply be ignored or an exception could be raised. If there was less elements than required, then, again depending on the situation, you could just ignore it (leave the final elements of the array uninitialised), or treat the missing elements in the supplied list as some default values. Or, again, raise an exception. – Andriy M Jun 27 '11 at 15:00
  • 2
    @Andriy Since you know how many there are in a fixed size array it's simply better to do the checking at compile time. – David Heffernan Jun 27 '11 at 15:07
  • 2
    Another benefit of the 'standard' helper function (as opposed to the open-array helper function) is that it tells the programmer in what order the red, green, and blue components are to be specified in. – Andreas Rejbrand Jun 27 '11 at 15:57
  • In Delphi 7 this constructor form does not work with a dynamic char array! TCharArray = array of char; (Object or class type required) :( – The Bitman Jun 10 '16 at 08:44
10

This is an area where Delphi turns something that is a simple one-line assignment statement in most languages into something more complicated.

One approach would to declare the value as a typed constant:

type
  HSVRealArray = array[1..3] of real;
const
  constHSVVal: HSVRealArray = (0, 0, 0);
var
  currentValue: HSVRealArray;
begin
  currentValue := constHSVVal;
end;

Another approach is to create utility functions that return the type you need:

function MakeHSVRealArray(H, S, V: Real): HSVRealArray;
begin
  Result[1] := H;
  Result[2] := S;
  Result[3] := V;
end;

currentValue := MakeHSVRealArray(0,0,0);
Dan Bartlett
  • 826
  • 7
  • 8
6

With some extra work, you can achieve a clean implementation:

var
    x: TRGB;
begin
    x := TRGB.Init(0,0,0);
end;

TRGB = record
    Red, Green, Blue: real;
    class function Init(r,g,b: real): TRGB; static;
end;

class function TRGB.Init(r, g, b: real): TRGB;
begin
    Result.Red := r;
    Result.Green := g;
    Result.Blue := b;
end;
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
markus_ja
  • 2,931
  • 2
  • 28
  • 36
  • 1
    +1. You might also make it a normal function (not a class function); then you can do `x.Init`. – Andreas Rejbrand Jun 27 '11 at 14:23
  • 2
    If you declare it as `constructor Init(...);` then you have the flexibility of either using it as a function: `x := TRGB.Init(...);` or as a procedure to initialise an existing instance: `x.Init(...);` – Disillusioned Apr 16 '14 at 15:28
5

Delphi-XE7 introduced a new syntax for dynamic array initialization.

// compile time const declaration of dynamic array
const
  my_ConstArray_name: TArray<Integer> = [128, 38459, 438, 23674];

// compile time var declaration of dynamic array
var
  my_VarArray_name: TArray<Integer> = [128, 38459, 438, 23674];

Runtime assignment of dynamic arrays:

var
  a : TArray<Integer>;
begin
  a := [1,2,3];

Unfortunately this syntax cannot be used on ordinary static arrays:

Type
  TMyArray = array[0..3] of Integer;  

const
  cMyArray: TMyArray = [0,1,2,3]; // E2010 Incompatible types: 'TMyArray' and 'Set'
  cMyArray: TMyArray = (0,1,2,3); // Works, as in all Delphi versions

var
  MyArray: TMyArray;
begin
  // This fails as well
  MyArray := [0,1,2,3]; // E2010 Incompatible types: 'TMyArray' and 'Set'
  MyArray := (0,1,2,3); // E2029 ')' expected but ',' found  
  //-----------^-------

  // This works in all Delphi versions !
  MyArray := cMyArray;
LU RD
  • 34,438
  • 5
  • 88
  • 296
5

For array handling, array initialization and array constant declarations, Delphi doesn't make simple things simple.

In some situations similar to yours, I initialize the array with a utility function taking one open array parameter and returning the appropiate static string.

const
    MaxArray = 10;
type
    TRealStaticArray = array[0..MaxArray] of Real;

function RealArray(const AnArray: array of real):TRealStaticArray;
    const DefaultValue=0.0;
    var i: integer;
    begin
        // EDIT: commented out, thanks Serg. for i:= 0 to low(AnArray)-1 do result[i]:=DefaultValue;
        for i:= High(AnArray)+1 to MaxArray do
            result[i]:=DefaultValue;
        for i:= Low(AnArray) to High(AnArray) do
            if (i>=0) and (i<=MaxArray) then
                result[i]:=AnArray[i];
    end;

Use it this way:

 var MyArray: TRealStaticArray;
 ...
 MyArray := RealArray([10.0, 20.0, 30.0]);
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
PA.
  • 28,486
  • 9
  • 71
  • 95
2

I know this is an old post, but I came across this while looking into the auto-assignment technique for Delphi. This post has a very nice explanation, along with a way to auto-assign an array of records:

http://delphi.about.com/od/adptips2006/qt/const_array.htm

Unfortunately, the initialization can only be done with native or record types. Class objects need a helper function as others have shown above.

James Jensen
  • 731
  • 1
  • 7
  • 14
  • 2
    Thank you very much for this information. Old question, new answer-seeker. ;-) But seriously we ought to be embarrassed that you can't simply assign the items at once in 2013. – alcalde Aug 14 '13 at 21:29
1

Putting aside the general question, I'd like to point out that the specific use-case was never going to work anyway: Delphi can't return on the stack the contents of an array of unknown length.

The return type of a function needs to be known by the calling code. It may be a pointer to the heap: it may even be a memory-managed object on the stack: but it is not permitted to be an undefined number of bytes on the stack, decided dynamically by the target function.

And in many other languages, the example

return (0,0,0)  //return pointer to automatic allocation

would be undefined, even if the compiler lets you do it.

A common method of defining, using and returning const values is

int myarray[8] = {128, 38459, 438 ... 23674};
memcpy (myparam, myArray, sizeof (myArray)); 

... and you can do that in Delphi

david
  • 2,435
  • 1
  • 21
  • 33
1

Can you try something like that:

TRGB = record
      Red  : integer;
      Green: integer;
      Bklue: integer;
  end;

var Variable:TRGB;

Variable.Red:=0;
Variable.Green:=0;
Variable.Blue:=0;
TreantBG
  • 1,192
  • 6
  • 25
  • 44
0

[0, 0, 0] is a set in Delphi. (0, 0, 0) is an array constant in Delphi! Just use:

HSVtoRGB := (0, 0, 0);

(Unless HSVtoRGB is a dynamic array. Did you declare it as var HSVtoRGB: array[1..3] of integer; or something similar?

Wim ten Brink
  • 25,901
  • 20
  • 83
  • 149