Sign in Join

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

Mailing lists / fpc-pascal / 2018-11

Uniform initialization?

15 messages · 6 people · –

Reply by email Subscribe to this list Your subscription

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

Ryan Joseph

Since I’ve got a little more free time I wanted to see if there was a simple solution to issue in Pascal that causes quite a bit of friction for me, i.e. constructor boiler plate. In c++ there is “uniform initialization” for structs which uses the {} syntax. It’s basically identically to record consts in Pascal, i.e.

type
  tvec2 = record
    x,y:integer;
  end;
var
  vec: tvec2 = (x:1;y1);

but it can be used at runtime (unlike Pascal which is compile time only). Many months ago I mentioned this and got a little positive response so I’d to ask again since I could probably implement it now.

Are any of these ideas appealing?

1) Simply move the typed const syntax down into blocks and use the type name like a function i.e.,

var
 vec:tvec2;
begin
 vec := tvec2(x:1;y1);

2) providing advanced records are on and perhaps a mode switch or some other kind of decorator, auto generate an implicit constructor, given no other constructors named “create" in the structure exist. i.e.,

{$something+}
type
  tvec2 = record
    x,y:integer;
  end;
{$something-}
var
 vec:tvec2;
begin
  vec := tvec2.create(1,1); // tvec2 has no constructor defined so “create” with all public member fields as parameters is implicitly defined
  vec := tvec2.create;	// “create” is a static class function with default values so we can do this
end.

Here is the proposed implicit constructor for tvec2:

class function create(_x:integer=default(integer);y:integer=default(integer)):tvec2;static;

I prefer #2 because it’s easiest to type and looks most natural to Pascal. Not sure what the downsides are even???

Regards,
Ryan Joseph

Ryan Joseph
to Unknown author
Show quoted text 14 lines
On Nov 11, 2018, at 10:03 PM, wrote: Hello, Delphi 10.3 is going to support inline variable declarations like this: begin var i : Integer := 22; WriteLn(i); end; I would assume it can also be used with records. For details, please see http://blog.marcocantu.com/blog/2018-october-inline-variables-delphi.html So maybe that's the route to go.

That’s interesting Delphi is breaking with the one of the oldest Pascal traditions. I have no idea what implications that would have for FPC or if it will be supported. If I recall this idea was shunned pretty thoroughly on the list a few months ago.

It’s still not a replacement for implicit constructors though since it’s tied to declaration time. Swift has implicit constructors for structs but uses the normal constructor syntax, unlike c++ which uses a special {} syntax. It really cuts down on boiler plate stuff when making new records. It’s a no-brainer for me and super easy to implement (already got most of it done today before I thought to ask) but lets see what people have to say.

Anonymous functions are still my biggest wish for FPC but they are considerably more complicated than what I can do currently.

Regards,
Ryan Joseph

Sven Barth
to Unknown author: Delphi 10.3 is going to support inline variable declarations like this: begin var i :…

Am 11.11.2018 um 16:03 schrieb

Show quoted text 12 lines
Hello, Delphi 10.3 is going to support inline variable declarations like this: begin var i : Integer := 22; WriteLn(i); end; I would assume it can also be used with records. For details, please see http://blog.marcocantu.com/blog/2018-october-inline-variables-delphi.html So maybe that's the route to go.

We've already decided internally that we are *not* going to support this.

Regards,
Sven

Sven Barth
to Ryan Joseph: Since I’ve got a little more free time I wanted to see if there was a simple solution…
Ryan Joseph wrote 42 lines
Since I’ve got a little more free time I wanted to see if there was a simple solution to issue in Pascal that causes quite a bit of friction for me, i.e. constructor boiler plate. In c++ there is “uniform initialization” for structs which uses the {} syntax. It’s basically identically to record consts in Pascal, i.e. type tvec2 = record x,y:integer; end; var vec: tvec2 = (x:1;y1); but it can be used at runtime (unlike Pascal which is compile time only). Many months ago I mentioned this and got a little positive response so I’d to ask again since I could probably implement it now. Are any of these ideas appealing? 1) Simply move the typed const syntax down into blocks and use the type name like a function i.e., var vec:tvec2; begin vec := tvec2(x:1;y1); 2) providing advanced records are on and perhaps a mode switch or some other kind of decorator, auto generate an implicit constructor, given no other constructors named “create" in the structure exist. i.e., {$something+} type tvec2 = record x,y:integer; end; {$something-} var vec:tvec2; begin vec := tvec2.create(1,1); // tvec2 has no constructor defined so “create” with all public member fields as parameters is implicitly defined vec := tvec2.create; // “create” is a static class function with default values so we can do this end. Here is the proposed implicit constructor for tvec2: class function create(_x:integer=default(integer);y:integer=default(integer)):tvec2;static; I prefer #2 because it’s easiest to type and looks most natural to Pascal. Not sure what the downsides are even???

I'm not convinced that this feature is really needed, because one can simply create a constant and assign that, would transport a clear name as well.
But *if* I had to decide I would pick #1, cause then there wouldn't be the chance to break existing code if a user decides to add a constructor to their record and some other code relies on there not being a constructor. Also due to the syntax
TYPENAME(FIELDNAME:VALUE[;FIELDNAME:VALUE[;…]]) it's in principle possible to have the parser distinguish whether it's a typecast or a default constructor.

Regards,
Sven

leledumbo
to Sven Barth
Show quoted text 7 lines
But *if* I had to decide I would pick #1, cause then there wouldn't be the chance to break existing code if a user decides to add a constructor to their record and some other code relies on there not being a constructor. Also due to the syntax TYPENAME(FIELDNAME:VALUE[;FIELDNAME:VALUE[;…]]) it's in principle possible to have the parser distinguish whether it's a typecast or a default constructor.

I would pick #1, too, seems more natural to me. There's no ambiguity as well thanks to : in the syntax. I do wonder how often this would be used, though. Despite being idiomatic in many languages, it doesn't really save much typing that traditional way (if that's the main purpose).

Sven Barth
to leledumbo
leledumbo wrote 11 lines
> But *if* I had to decide I would pick #1, cause then there wouldn't be > the chance to break existing code if a user decides to add a constructor > to their record and some other code relies on there not being a > constructor. Also due to the syntax > TYPENAME(FIELDNAME:VALUE[;FIELDNAME:VALUE[;…]]) it's in principle > possible to have the parser distinguish whether it's a typecast or a > default constructor. I would pick #1, too, seems more natural to me. There's no ambiguity as well thanks to : in the syntax. I do wonder how often this would be used, though. Despite being idiomatic in many languages, it doesn't really save much typing that traditional way (if that's the main purpose).

Especially if you're using the same initialization values more often you'd safe more time by declaring a suitable constant and using that as the IDE can help you with code completion when using the constant.

Regards,
Sven

Vojtěch Čihák
to Unknown author: Delphi 10.3 is going to support inline variable declarations like this: begin var i :…

Very good.
 
V.
______________________________________________________________

Show quoted text 5 lines
Od: "Sven Barth via fpc-pascal" Komu: Datum: 11.11.2018 18:22 Předmět: Re: [fpc-pascal] Uniform initialization?

Am 11.11.2018 um 16:03 schrieb

Show quoted text 12 lines
Hello, Delphi 10.3 is going to support inline variable declarations like this: begin    var i : Integer := 22;    WriteLn(i);    end; I would assume it can also be used with records. For details, please see http://blog.marcocantu.com/blog/2018-october-inline-variables-delphi.html <http://blog.marcocantu.com/blog/2018-october-inline-variables-delphi.html> So maybe that's the route to go.

We've already decided internally that we are *not* going to support this.

Regards,
Sven

Ryan Joseph
to Sven Barth: I'm not convinced that this feature is really needed, because one can simply create a…
On Nov 12, 2018, at 12:25 AM, Sven Barth via fpc-pascal wrote: I'm not convinced that this feature is really needed, because one can simply create a constant and assign that, would transport a clear name as well.

This is for runtime though and necessarily for constants. It’s just a short hand for initializing records so you don’t need to make boiler plate constructors. Often time when you create a new record you add a constructor so you can init in one line. Swift and c++ both have this default constructor and it’s a nice time saver.

for example:

struct Vec2 {
	float x,y;
};
int main() {
	Vec2 v = {1,2};
	v = {v.x + 1, v.y + 1};
	return 0;
}
But *if* I had to decide I would pick #1, cause then there wouldn't be the chance to break existing code if a user decides to add a constructor to their record and some other code relies on there not being a constructor. Also due to the syntax TYPENAME(FIELDNAME:VALUE[;FIELDNAME:VALUE[;…]]) it's in principle possible to have the parser distinguish whether it's a typecast or a default constructor.

Yeah there could be name conflicts then. Maybe there should be some way to explicitly state you want the constructor with a certain name, i.e.,

type
	TVec2 = record
		x, y: integer;
		constructor create; default;
	end;

??? I don’t know, just an idea.

Regards,
Ryan Joseph

Sven Barth
to Ryan Joseph

Am Mo., 12. Nov. 2018, 03:12 hat Ryan Joseph
geschrieben:

Show quoted text 27 lines
> On Nov 12, 2018, at 12:25 AM, Sven Barth via fpc-pascal < > wrote: > > I'm not convinced that this feature is really needed, because one can simply create a constant and assign that, would transport a clear name as well. This is for runtime though and necessarily for constants. It’s just a short hand for initializing records so you don’t need to make boiler plate constructors. Often time when you create a new record you add a constructor so you can init in one line. Swift and c++ both have this default constructor and it’s a nice time saver. for example: struct Vec2 { float x,y; }; int main() { Vec2 v = {1,2}; v = {v.x + 1, v.y + 1}; return 0; }

The advantage of the typecast like syntax is that you can get compiler errors if for whatever reason the order of the fields is changed as they are all named.

Show quoted text 18 lines
> But *if* I had to decide I would pick #1, cause then there wouldn't be the chance to break existing code if a user decides to add a constructor to their record and some other code relies on there not being a constructor. Also due to the syntax TYPENAME(FIELDNAME:VALUE[;FIELDNAME:VALUE[;…]]) it's in principle possible to have the parser distinguish whether it's a typecast or a default constructor. Yeah there could be name conflicts then. Maybe there should be some way to explicitly state you want the constructor with a certain name, i.e., type TVec2 = record x, y: integer; constructor create; default; end; ??? I don’t know, just an idea.

That is a constructor that takes no arguments. How do you think that is useful for a constructor that *does* take arguments? That is absolutely not clear at all for the user.

Regards,
Sven

Ryan Joseph
to Sven Barth
On Nov 12, 2018, at 1:55 PM, Sven Barth via fpc-pascal wrote: That is a constructor that takes no arguments. How do you think that is useful for a constructor that *does* take arguments? That is absolutely not clear at all for the user.

I just meant as a label so you know the record has a default constructor associated with it and it’s named. You’re right about the fields changing place and breaking constructors.

Honestly if the syntax is the type cast I probably would just make a constructor anyways because it’s less typing in the end. What I was really after is a way to save time making boiler plate constructers for records that merely hook up params to fields.

It feels like this is in the sprite of what properties aimed to accomplished, i.e. making getting/setters easier to manage.

Given that is there any syntax based off properties you would accept? Otherwise probably best to let this one rest.

I managed to get the syntax parsed for the type cast but not sure how to build the nodes or if it should point to a hidden constructor (lots of overhead in that case). Maybe I’ll come back to that later.

Regards,
Ryan Joseph

Sven Barth
to Ryan Joseph

Am Di., 13. Nov. 2018, 07:04 hat Ryan Joseph
geschrieben:

Show quoted text 11 lines
> On Nov 12, 2018, at 5:45 AM, Vojtěch Čihák wrote: > > We've already decided internally that we are *not* going to support this. Why does FPC have Delphi mode anyways? It’s not actually compatible with Delphi so what is it used for? It seems like if you’re a Delphi user you would just use the Delphi compiler.

The idea of the mode was to support Delphi code as much as possible, yes, but in the past years the Delphi language has turned more and more into a butchering of the Object Pascal language, a butchering that we don't want to continue to support.
If it means missing out on some users that might have chosen FPC then so be it. There are enough people that either start with FPC without any Delphi background or that move over from an older version of which we do support the features.

Regards,
Sven

Martin Wynne
to Sven Barth

Delphi mode is very useful.

It means old code from earlier versions of Delphi (in my case Delphi5) can be open-sourced and made available via Lazarus to anyone interested, without their needing to get an expensive copy of the latest Delphi.

Martin.

Vojtěch Čihák
to Sven Barth: Am Di., 13. Nov. 2018, 07:04 hat Ryan Joseph geschrieben: The idea of the mode was to…

IMO 100% Delphi compatibility was important some 10 years back when Kylix was discontinued and peope wanted to port their old Delphi projects to Linux. From that time boh FPC and Lazarus are mature enough and everyone who started a new project after - let's say - 2008 had to do the decision: Delphi or FPC+Laz.  
V.
______________________________________________________________

Show quoted text 5 lines
Od: "Martin Wynne" Komu: Datum: 13.11.2018 11:11 Předmět: Re: [fpc-pascal] Uniform initialization?

Delphi mode is very useful.

It means old code from earlier versions of Delphi (in my case Delphi5) can be open-sourced and made available via Lazarus to anyone interested, without their needing to get an expensive copy of the latest Delphi.

Martin.