[fpc-devel] va(r)_arg vs open array

Daniël Mantione daniel.mantione at freepascal.org
Mon Oct 2 22:13:15 CEST 2006



Op Mon, 2 Oct 2006, schreef ik:

> > Well, I think that this is also a functional thing.
> > 
> > >
> > > * Syntactically, both methods can be safe.
> > > * Syntactically, the FPC/Delphi one is more powerfull.
> > 
> > Well take a look at the way Java implement it:
> > 
> > .... function varrags(String ... a)
> > {
> >    for (int i = 0; i<= a.length; i++)
> >    {
> >       a[i] ...
> >    }
> > }
> > 
> > varags(a,b,c,d,e,f,g);
> > 
> > The thing I wish that you'll see is that here it's pure array like in
> > Pascal, but the array is part of the content of the function and not
> > part of the parameter usage ... (I can btw also use different types,
> > so we solve the problem of unsafe types).

You can have an array with a multitude of types in Java, but in Pascal 
this is not possible in Pascal. I.e. translating it to Pascal could be:

1  procedure varargs(a:...);
2
3  begin
4    for i:=low(a) to high(a) do
5      writeln(a[i]);
6  end;
7
8  begin
9   varargs(0.0, at varargs,[1,2,3],true);
10 end.

In Pascal the combination of line 5 and line 9 is unacceptable. We are a 
strongly typed language with static types. C can accept it because it is 
type unsafe. Java can accept it because the types are determined at 
runtime, with a big speed penalty of course.

A variant record is the proper solution. If you expect numbers, you access 
the Vinteger field. Expect a boolean? Use the Vboolean field. As a bonus, 
you can check the types of the parameters passed, and check them at 
runtime for extra safety.

> > BTW in perl every group of scalars are actually an array... there is
> > no difference .

Perl has no static typing.

> > > > The [] is the same as "InitbyObject". It's informative, but not really
> > needed.
> > >
> > > The [] is the mechanism that allows you to pass multiple arrays.
> > 
> > I don't understand what you mean :(

Multiple arrays is not possible in C:

procedure write_list_row(const fields:array of string;const widths:array of byte);

begin
  assert(high(fields)=high(widths);

  for i:=low(fields) to high(fields)
    writeln(fields[i]:widths[i]);
end;

begin
  write_list_row(['Language','Strong/weak','dynamic/static'],[20,15,15]);
  write_list_row(['Pascal','strong','static'],[20,15,15]);
  write_list_row(['C','weak','static'],[20,15,15]);
  write_list_row(['Java','strong','dynamic'],[20,15,15]);
end;

This can be achieved thanks to the [].

> > > > Cool, but if you want to do better, then lets get one step further and
> > > > say that nil value does not need to be "0 amount of values" in the
> > > > parameter usage itself. Why not just to check
> > > >
> > > > if (not openarray = nil) then ...
> > > >
> > > > ?
> > >
> > > Huh, I don't understand this?
> > 
> > If I will not add any parameter, I could check inside the function if
> > the parameter is initilized rather then checking for length, so []
> > will be for 0 items while, no "[]" will be no parameters at all.

Not possible. The array is can be passed by value. It is the same thing 
that in "procecure x(y:byte)" variable y is mandatory, there is no way you 
can pass nothing.

> > > Well, if it were to the Free Pascal developers, there would be no
> > default
> > > values at all :) We heavily grumbled when we had to implement it to be
> > > Delphi compatible.
> > 
> > But we can see how good and helpful it is and can accept it :)

No, it sucks big time, IMHO. It is one the VB things Borland should not 
have put into Delphi. We've always had the opinion that an overload is the 
proper solution.

> > With an integer parameter, you can place "0" for example as default
> > parameter, so with open array, you could also place default paramters,
> > when #0 was just an example for that.

Sure, we can implement that. But we are no fans of default parameters, and 
you have to stop somewhere, i.e. you want to avoid people putting complete 
constant record definitions in a procedure header. Simple types only.

> > > > > > 5. Feel like an hack.
> > > > >
> > > > > Where do you get that feeling?
> > > >
> > > > "OK, so I don't have a way to make a compiler voodoo magic, but I can
> > > > use an open array to get the closer feeling", but as Daniel say, in
> > > > order to complete the usage of such thing, I need a synthetic sugar,
> > > > and that does not implemented... It does not feel native ... it feels
> > > > like a patch/hack that was added to shout people up when they say "you
> > > > do not have var args".
> > >
> > > On the contrary. I think we can consider constant arrays native? Then
> > > there is nothing about bad about reusing the principle. IMHO. Feel free
> > to
> > > differ, but I consider the [] solution much more elegant than the C
> > > varargs.
> > 
> > Yes and no, it is more elegant, but with few prices ...

There is a price, and that is that FPC pushes the type of the parameter, 
instead of just the value. I'll stick my fingers in my ears until I hear 
someone complaining that his code is too slow because of that :P

> > > Actually I agree with you here.
> > 
> > Finally :) What does it take to make it non object oriented thingy,
> > that is, it can be used on $MODE FPC ?

See thread "Suggestion for change". Propose it, defend that it is 
necessary. If you can defend it, I'll enable it.

> > > > Back in the Delphi2-3 days (maybe its till exists), there was a hack
> > > > that if a variable is from a range of 000000..111111 it is an integer,
> > > > if the range of the memory is 222222..333333 the variable is float, if
> > > > it's AAAAAA..FFFFFF it's a class etc.. you don't expect any developer
> > > > to go that law to know such things ... specially, that it is not a
> > > > constant thing on every OS and arch .
> > >
> > > Huh?!! Again I am lost.
> > 
> > I'd seen hacks to find what is the parameter type (in delphi), by
> > getting the memory address of that paramter, and the position inside a
> > range of memory that the parameter located at, reprisent the type of
> > that parameter.

??? Why would that be necessary? You need it in C, but in FPC/Delphi, the 
type is in the varrec. 

> > > > So how good are we then the C developers, that pointers are like air
> > > > to them, even on places no other language really needs them (including
> > > > c++) ?
> > > >
> > > > "Maybe we should use object like variable types ?" (don't even bother
> > > > to answer, I don't want such a thing)
> > >
> > > I don't think there is an alternative here. If you would pass an array
> > of
> > > pointers, you would get into trouble when passing integers. (Pascal
> > > is type safe.) Record variants are the only sensible solution.
> > 
> > I do not like variants. They are very memory weasting type, and most
> > of the time operator overloading might make a better job.

Hola, do not confuse variants with variant records. A variant is this:

var a:variant;

... and is such a memory weasting thing, but a variant record is this:

type t=record
       case boolean of
         false:(p:longint);
         true:(p:pointer)';
     end;

... which doesn't waste a single byte.


Daniël


More information about the fpc-devel mailing list