Sign in Join

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

Mailing lists / fpc-pascal / 2018-04

compile time init'ing records

9 messages · 3 people ·

Reply by email Subscribe to this list Your subscription

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

Ryan Joseph

It’s a real pain setting default values for records in Pascal at compile time. Every other language seems to get this right but it’s a constant issue in Pascal. The new "class operator Initialize” feature goes a long way in helping this but it’s still a little annoying that the function is down in the implementation and taking up space plus requires scrolling etc… Static class methods help also but again the function is detached from the record and needs to be called manually.

Why can’t we just do something simple like this? A simple meta programming hack to dump the “default” section at the start of the scope the variable is declared in so we don’t have to do this ourselves every time. It probably breaks down for init’ing records but for compiler types it seems pretty simple.

type
	TMyRecord = record
		public
			i: integer;
			s: string;
		default
			i := 1;
			s := 'foo';
	end;
var
	myRec: TMyRecord; default; // if no default section is specified then use FillChar(this, sizeof(this), 0);
begin
	// the compiler copy/pastes the variables "default" section at start of the scope
	myRec.i := 1;
	myRec.s := 'foo';
end;

Regards,
Ryan Joseph

Reply by email

Maciej Izak
to Ryan Joseph

2018-04-13 5:02 GMT+02:00 Ryan Joseph :

Show quoted text 6 lines
Why can’t we just do something simple like this? A simple meta programming hack to dump the “default” section at the start of the scope the variable is declared in so we don’t have to do this ourselves every time. It probably breaks down for init’ing records but for compiler types it seems pretty simple.

No need for something like new default section. You can just use :

===code begin===
{$MACRO ON}
{$DEFINE TMyRecord_Default := (i: 1; s: 'foo')}
type
  TMyRecord = record
    i: integer;
    s: string;
  end;
var
  myRec: TMyRecord = TMyRecord_Default;
===code end===

you can also try new management operator "Initialize":

http://wiki.freepascal.org/management_operators

Best regards, Maciej Izak

Reply by email

Maciej Izak
to Marco van de Voort

2018-04-13 10:29 GMT+02:00 Marco van de Voort :

p.s. does r:=default(r); do anything ? Or does that only work in generics?
works for non-generics types too, can be used instead of FillChar(..,..,0);
Best regards, Maciej Izak

Reply by email

Ryan Joseph
to Marco van de Voort: In our previous episode, Ryan Joseph said: Because it is very limited and forces the…
On Apr 13, 2018, at 3:29 PM, Marco van de Voort wrote: Because it is very limited and forces the initialization at the place of declaration, which is rare if not zero.

When using other languages I use it often. The fact that all other modern languages I’m aware of support it says something also (even c++!). Granted 0 is most common it’s still very helpful to init at time of declaration because you were just going to do it yourself anyways at the start of the scope. It’s such a common pattern but Pascal is out dated on this front. Records don’t have default constructors also like other modern languages so they need some work in my opinion.

{$DEFINE TMyRecord_Default := (i: 1; s: 'foo’)} is an interesting idea but unfortunately it’s a bit of a hack.
p.s. does r:=default(r); do anything ? Or does that only work in generics?

I didn’t know Default worked with all types and replaces the more verbose FillChar call. That’s a step in the right direction.

Regards,
Ryan Joseph

Reply by email

Ryan Joseph
to Maciej Izak
On Apr 13, 2018, at 4:27 PM, Maciej Izak wrote: FPC has "Initialize" operator for such purposes : http://wiki.freepascal.org/management_operators

These are great and one of the best features to be added in a while but that’s not the same. I mean a default constructor like Create() which the compiler automatically generates and takes as parameters the fields of the record. Making the same boiler plate constructors for records all the time is not so great.

var
  rec: TPoint;
begin
  rec := TPoint(x: 100, y: 100);

I mentioned this some time ago since Pascal already has that syntax for init records at compile time. Now that I mention it, you could use the same syntax with no arguments to zero the record.

var
  rec: TPoint = ();
begin

Regards,
Ryan Joseph

Reply by email

Maciej Izak
to Ryan Joseph

2018-04-13 11:54 GMT+02:00 Ryan Joseph :

Show quoted text 11 lines
These are great and one of the best features to be added in a while but that’s not the same. I mean a default constructor like Create() which the compiler automatically generates and takes as parameters the fields of the record. Making the same boiler plate constructors for records all the time is not so great. var rec: TPoint; begin rec := TPoint(x: 100, y: 100);

Yes you are right. IIRC someone from core team has similar vision (Sven?), IMO good direction :). Something like this is also on my TODO list (but not with high priority).

Best regards, Maciej Izak

Reply by email

Ryan Joseph
to Maciej Izak
On Apr 13, 2018, at 5:31 PM, Maciej Izak wrote: Yes you are right. IIRC someone from core team has similar vision (Sven?), IMO good direction :). Something like this is also on my TODO list (but not with high priority).

Sven agreed with me already on this if I remember correctly. I would do it myself if I could even begin to understand the compiler code base in the slightest. :) Seriously through if there were good resources on how to contribute that would go a long way in helping others contribute.

Regards,
Ryan Joseph

Reply by email