Question

Using D2010, I'd like to do something like this:

procedure SizeArray(var aArr: array of integer; aSize: integer);
begin
  SetLength(aArr,aSize);
end;

But this fails to compile. Because my "aArr" parameter isn't a dynamic array, it's an open array parameter. And SetLength cannot be called on it. The only way I know of to force the parameter to be a dynamic array is to give it a type name, like so:

type
  TIntArray = array of integer;

procedure SizeArray(var aArr: TIntArray; aSize: integer);
begin
  SetLength(aArr,aSize);
end;

And now the code compiles. And it works fine, for the most part, but this fails:

procedure Test;
var
  a : array of integer;
begin
  SizeArray(a,5);
end;

Because types of actual and formal var parameters must be identical and the compiler doesn't recognize "array of integer" and "TIntArray" as identical types.

So, here's my question: Is there some way I can get the compiler to identify my var parameter as a dynamic array rather than as an open array so that the caller can declare a simple "array of integer" rather than some named type?

Thanks in advance.

Was it helpful?

Solution

Pascal, and by extension Delphi, uses name equivalence rather than structural equivalence for array types, including dynamic arrays. Variables declared with a type that doesn't have a name, like this:

var
  x: array of Integer;

... end up using an anonymous name that isn't equivalent to any other type's name. That's why you get the error. The error can be useful; for example, consider an array of Kilometers vs an array of Kilograms - but it's often the case that declaring a name for every distinct type is inconvenient.

To get around this issue, and staying within the safe type system (so avoiding untyped parameters, as skamradt suggests), I recommend using the same name for every particular array shape. You can do this to a reasonably large degree by using the TArray<T> type declared in the System unit. So, instead of working with array of Integer, use TArray<Integer>.

TArray<T> is declared like this:

type
  TArray<T> = array of T;

... so it can supply a name for arbitrary dynamic arrays.

OTHER TIPS

This is indeed possible...just use the absolute keyword along with an untyped var.

procedure SizeArray(var aArr; aSize: integer);
var
  ActArr : Array of Integer absolute aArr;
begin
  SetLength(ActArr,aSize);
end;

var
  Test : Array of Integer;
begin
  SizeArray(Test,5);
  showMessage(IntTostr(High(Test)));  // -- returns 4
end;

No, there's no way to do that. It's part of the Pascal language specification and isn't likely to change.

EDIT: Skamradt found a way. Let me restate that. There's no way to do that safely.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top