Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-pascal / 2007-05

Dynamic array as return type of functions

7 messages · 4 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Christos Chryssochoidis

Hi,

I tried to write some function that returned a dynamic array, and realized that this isn't allowed. Why? After all one can specify an array of variable length as type for variables... Furthermore - if I'm not mistaken - a dynamic array is implemented internally as a pointer, and so there wouldn't be any runtime overhead for returning a dynamic array from a function.

Thanks,

Christos Chryssochoidis

Michalis Kamburelis
to Christos Chryssochoidis
Christos Chryssochoidis wrote 9 lines
Hi, I tried to write some function that returned a dynamic array, and realized that this isn't allowed. Why? After all one can specify an array of variable length as type for variables... Furthermore - if I'm not mistaken - a dynamic array is implemented internally as a pointer, and so there wouldn't be any runtime overhead for returning a dynamic array from a function.

It *is* allowed. The only trick is that you have to declare a type for your dynamic array, i.e. you have to write something like

  type TDynInts = array of Integer;
  function MakeArray: TDynInts;

instead of

  function MakeArray: array of Integer;

This quick example compiles fine in objfpc mode:

type
  TDynInts = array of Integer;
function MakeArray: TDynInts;
begin
  SetLength(Result, 2);
  Result[0] := 0;
  Result[1] := 1;
end;
var
  A: TDynInts;
begin
  A := MakeArray;
  Writeln(A[0], ' ', A[1]);
end.

Michalis

Daniël Mantione
to Michalis Kamburelis

Op Wed, 23 May 2007, schreef Michalis Kamburelis:

Show quoted text 13 lines
Christos Chryssochoidis wrote: > Hi, > > I tried to write some function that returned a dynamic array, and > realized that this isn't allowed. Why? After all one can specify an > array of variable length as type for variables... Furthermore - if I'm > not mistaken - a dynamic array is implemented internally as a pointer, > and so there wouldn't be any runtime overhead for returning a dynamic > array from a function. > It *is* allowed. The only trick is that you have to declare a type for your dynamic array, i.e. you have to write something like

I think this is one more example open array versus dynamic array confusion. Arrays declared in type statements are dynamic arrays; arrays declared in procedure/function headers are open arrays. You can return a dynamic array, but not an open array.

Daniël

Christos Chryssochoidis
to Daniël Mantione
Daniël Mantione wrote 32 lines
Op Wed, 23 May 2007, schreef Michalis Kamburelis: > Christos Chryssochoidis wrote: >> Hi, >> >> I tried to write some function that returned a dynamic array, and >> realized that this isn't allowed. Why? After all one can specify an >> array of variable length as type for variables... Furthermore - >> if I'm >> not mistaken - a dynamic array is implemented internally as a >> pointer, >> and so there wouldn't be any runtime overhead for returning a >> dynamic >> array from a function. >> > > It *is* allowed. The only trick is that you have to declare a type > for > your dynamic array, i.e. you have to write something like I think this is one more example open array versus dynamic array confusion. Arrays declared in type statements are dynamic arrays; arrays declared in procedure/function headers are open arrays. You can return a dynamic array, but not an open array. Daniël_______________________________________________ fpc-pascal maillist - http://lists.freepascal.org/mailman/listinfo/fpc-pascal

Yes, I have noticed that if you first wrap a dynamic array in a type definition then you can declare a function returning such an array, but it seemed to me as an unnecessary complication of things and as an inconsistency in the language. However, the distinction between dynamic and open arrays that D.Mantione says, explains this complication.

Thanks very much for your answers,

Christos

Tom Verhoeff
to Christos Chryssochoidis
Christos Chryssochoidis wrote 10 lines
>>It *is* allowed. The only trick is that you have to declare a type for >>your dynamic array, i.e. you have to write something like Yes, I have noticed that if you first wrap a dynamic array in a type definition then you can declare a function returning such an array, but it seemed to me as an unnecessary complication of things and as an inconsistency in the language. However, the distinction between dynamic and open arrays that D.Mantione says, explains this complication.

It is not a trick, but has to do with type compatibility issues (and history, I guess).

If you have

function f(...): SomeType;

then the result of calling f needs to go somewhere. Either it "disappears" as an intermediate result in a larger expression, or you assign it to a variable (or such). In case it is a subexpression, the result of f acts as a parameter of an enclosing function or operator.

while f(...) operator ... do ...

if g( f(...) ) then ...

  v := f(...)

The receiving parameter or variable needs to have a type "compatible" with SomeType. If SomeType is a type expression, then you cannot declare a parameter or variable of the same type by copying the type expression. In Pascal,

var
  a: array [ Char ] of Integer;
  b: array [ Char ] of Integer;
function g(p: array [ Char ] of Integer);
function f(c: Char; i: Integer): array [ Char ] of Integer;

does not (automatically) make a and b have the same type (in some cases automatic conversions etc. will give you some kind of compatibility).

For that (partly historic) reason, parameter types and return types must be type names and not type expressions.

Of course, there situations where you can argue that it works without using type names. E.g. if you return a record type, one way of using it would be to select a field:

function f(...): record x, y: Integer end;
  if f(...).x = 0 then ...

The "operation" of field selection works on arbitrary record types. Insisting on a type name seems unneeded. I.e. the typing of the "parameters" of . is not so strict; it occurs in a context

record . fieldname_of_this_record_type

The record is not a parameter of . in the usual sense.

I haven't checked the FPC documentation on all this.

Tom

E-MAIL: T.Verhoeff @ TUE.NL | Dept. of Math. & Comp. Science PHONE: +31 40 247 41 25 | Technische Universiteit Eindhoven FAX: +31 40 247 54 04 | PO Box 513, NL-5600 MB Eindhoven http://www.win.tue.nl/~wstomv/ | The Netherlands
Christos Chryssochoidis
to Tom Verhoeff
Tom Verhoeff wrote 82 lines
On Wed, May 23, 2007 at 11:36:20AM +0300, Christos Chryssochoidis wrote: > >>> It *is* allowed. The only trick is that you have to declare a >>> type for >>> your dynamic array, i.e. you have to write something like > > Yes, I have noticed that if you first wrap a dynamic array in a type > definition then you can declare a function returning such an array, > but it seemed to me as an unnecessary complication of things and as > an inconsistency in the language. However, the distinction between > dynamic and open arrays that D.Mantione says, explains this > complication. It is not a trick, but has to do with type compatibility issues (and history, I guess). If you have function f(...): SomeType; then the result of calling f needs to go somewhere. Either it "disappears" as an intermediate result in a larger expression, or you assign it to a variable (or such). In case it is a subexpression, the result of f acts as a parameter of an enclosing function or operator. while f(...) operator ... do ... if g( f(...) ) then ... v := f(...) The receiving parameter or variable needs to have a type "compatible" with SomeType. If SomeType is a type expression, then you cannot declare a parameter or variable of the same type by copying the type expression. In Pascal, var a: array [ Char ] of Integer; b: array [ Char ] of Integer; function g(p: array [ Char ] of Integer); function f(c: Char; i: Integer): array [ Char ] of Integer; does not (automatically) make a and b have the same type (in some cases automatic conversions etc. will give you some kind of compatibility). For that (partly historic) reason, parameter types and return types must be type names and not type expressions. Of course, there situations where you can argue that it works without using type names. E.g. if you return a record type, one way of using it would be to select a field: function f(...): record x, y: Integer end; if f(...).x = 0 then ... The "operation" of field selection works on arbitrary record types. Insisting on a type name seems unneeded. I.e. the typing of the "parameters" of . is not so strict; it occurs in a context record . fieldname_of_this_record_type The record is not a parameter of . in the usual sense. I haven't checked the FPC documentation on all this. Tom -- E-MAIL: T.Verhoeff @ TUE.NL | Dept. of Math. & Comp. Science PHONE: +31 40 247 41 25 | Technische Universiteit Eindhoven FAX: +31 40 247 54 04 | PO Box 513, NL-5600 MB Eindhoven http://www.win.tue.nl/~wstomv/ | The Netherlands _______________________________________________ fpc-pascal maillist - http://lists.freepascal.org/mailman/listinfo/fpc-pascal

I see. If I understand well, Pascal uses some sort of declaration equivalence for types.

Christos

Tom Verhoeff
to Christos Chryssochoidis
Christos Chryssochoidis wrote 8 lines
On 23 Μαϊ 2007, at 3:05 ΜΜ, Tom Verhoeff wrote: >It is not a trick, but has to do with type compatibility issues >(and history, I guess). I see. If I understand well, Pascal uses some sort of declaration equivalence for types.

Correct. In general, it is costly (or even hard/impossible) for a compiler to determine equivalence of type _expressions_.

Variables and parameters declared with the same type _name_ are (obviously) of the same type.

Tom

E-MAIL: T.Verhoeff @ TUE.NL | Dept. of Math. & Comp. Science PHONE: +31 40 247 41 25 | Technische Universiteit Eindhoven FAX: +31 40 247 54 04 | PO Box 513, NL-5600 MB Eindhoven http://www.win.tue.nl/~wstomv/ | The Netherlands