Discussion:
[fpc-pascal] Default record const values
Ryan Joseph
2018-11-10 08:35:00 UTC
Permalink
Should’t this work? This would be a good way to set default record values but it doesn’t seem to be supported.


type
TMyRecord = record
public
a: integer;
b: string;
const
default: TMyRecord = (a: 100; b: 'foo');
end;

var
r: TMyRecord = TMyRecord.default;


Regards,
Ryan Joseph

_______________________________________________
fpc-pascal maillist - fpc-***@lists.freepascal.org
http://lists.freepascal.org/cgi-bin/mailman/listi
Sven Barth via fpc-pascal
2018-11-10 09:55:44 UTC
Permalink
Should’t this work? This would be a good way to set default record values
but it doesn’t seem to be supported.
TMyRecord is not yet completely parsed. There could be another field
located behind the "default" constant. Thus using the type of the record
aside from Pointers and method parameters and result is not allowed.

Regards,
Sven
Ryan Joseph
2018-11-10 11:14:17 UTC
Permalink
Not quite understanding how that’s not entirely parsed by the time you assign outside of the record. Even so I would expect it to copy what the const was able to capture, fully parsed or not.

Also, why does it work to do

begin
r := TMyRecord.default;

in the main block?
TMyRecord is not yet completely parsed. There could be another field located behind the "default" constant. Thus using the type of the record aside from Pointers and method parameters and result is not allowed.
Regards,
Ryan Joseph

_______________________________________________
fpc-pascal maillist - fpc-***@lists.freepascal.org
http://lists.free
Sven Barth via fpc-pascal
2018-11-10 13:21:16 UTC
Permalink
Not quite understanding how that’s not entirely parsed by the time you
assign outside of the record. Even so I would expect it to copy what the
const was able to capture, fully parsed or not.
It's not entirely parsed by the time the constant is declared. That is
simply illegal code.
Also, why does it work to do
begin
r := TMyRecord.default;
in the main block?
It's not possible to use typed constants as initializers for variables.

Regards,
Sven
Ryan Joseph
2018-11-10 11:17:14 UTC
Permalink
This also fails.

type
TMyRecord = record
public
a: integer;
b: string;
end;
const
TMyRecord_Default: TMyRecord = (a: 100; b: 'foo');

var
r: TMyRecord = TMyRecord_Default;
TMyRecord is not yet completely parsed. There could be another field located behind the "default" constant. Thus using the type of the record aside from Pointers and method parameters and result is not allowed.
Regards,
Ryan Joseph

_______________________________________________
fpc-pascal maillist - fpc-***@lists.freepascal.org
http://lists.freepascal.org/cgi-bin/mailman/listinf
Martok
2018-11-12 11:59:37 UTC
Permalink
This post might be inappropriate. Click to display it.
Ben Grasset
2018-11-10 23:51:22 UTC
Permalink
Should’t this work? This would be a good way to set default record values
but it doesn’t seem to be supported.
Personally I think the answer here is keep working on your new/alternate
implementation of default field functionality! It's a missing puzzle piece
for FPC generics in many ways.
Ryan Joseph
2018-11-11 01:33:33 UTC
Permalink
Personally I think the answer here is keep working on your new/alternate implementation of default field functionality! It's a missing puzzle piece for FPC generics in many ways.
Not sure how default fields in generics help here. I just thought it would be nice if FPC supported this so we can init records at compile time easier. I’d prefer default struct fields like C++ has but typed const defaults would be an improvement.

I looked at the sources and in ttypedconstbuilder.read_typed_const_data (I think) it simply doesn’t support default record values with typed consts, only the = (a:x;b:x) style syntax. The typed const in the class was clearly defined as a hidden static var but I couldn’t figure out how to assign the values. Maybe I’ll look into it later.

Regards,
Ryan Joseph

_______________________________________________
fpc-pascal maillist - fpc-***@lists.freepascal.org
http://lists.freepascal.org/cgi-bin/mai
Ben Grasset
2018-11-11 03:08:35 UTC
Permalink
Post by Ryan Joseph
Not sure how default fields in generics help here. I just thought it would
be nice if FPC supported this so we can init records at compile time
easier. I’d prefer default struct fields like C++ has but typed const
defaults would be an improvement.
I guess I just meant that the other work you did recently seems (to me) to
be in roughly the same "category" of functionality, and that it was also
proof that there's not a whole lot of distance to close as far as the
actual code required to implement it in FPC with regards to that kind of
thing.
Sven Barth via fpc-pascal
2018-11-11 22:06:44 UTC
Permalink
Post by Ryan Joseph
Should’t this work? This would be a good way to set default record values but it doesn’t seem to be supported.
type
TMyRecord = record
public
a: integer;
b: string;
const
default: TMyRecord = (a: 100; b: 'foo');
end;
The compiler now correctly rejects such declarations with a "Type is not
completely defined error".

Regards,
Sven
_______________________________________________
fpc-pascal maillist - fpc-***@lists.freepascal.org
http://lists.freepascal.org/cgi-bin/mailman/list
Ryan Joseph
2018-11-12 01:08:19 UTC
Permalink
The compiler now correctly rejects such declarations with a "Type is not completely defined error".
But this syntax worked if you assigned it within blocks. Why does it need to be removed? Since I discovered it I was planning on using it instead of class functions with default values which require an implementation and are much longer to write.



Regards,
Ryan Joseph

_______________________________________________
fpc-pascal maillist - fpc-***@lists.freepascal.org
http://lists.freepascal.org/cgi-bin/mailman/
Ryan Joseph
2018-11-12 01:20:56 UTC
Permalink
Post by Ryan Joseph
But this syntax worked if you assigned it within blocks. Why does it need to be removed? Since I discovered it I was planning on using it instead of class functions with default values which require an implementation and are much longer to write.
Here’s an example of what I was doing before. A constant is so much better and doesn’t require the implementation and we still get the same . syntax, i.e., TPoint.Up.

Instead of removing it maybe give the error unless it’s the last field of the record and in which case can assumed to be fully defined.

type
TPoint = record
x: TFloat;
y: TFloat;
class function Up (_x: TFloat = 0; _y: TFloat = -1): TPoint; static; inline;

Regards,
Ryan Joseph

_______________________________________________
fpc-pascal maillist - fpc-***@lists.freepascal.org
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pasc
Sven Barth via fpc-pascal
2018-11-12 06:51:02 UTC
Permalink
Post by Ryan Joseph
Post by Ryan Joseph
But this syntax worked if you assigned it within blocks. Why does it
need to be removed? Since I discovered it I was planning on using it
instead of class functions with default values which require an
implementation and are much longer to write.
Here’s an example of what I was doing before. A constant is so much better
and doesn’t require the implementation and we still get the same . syntax,
i.e., TPoint.Up.
Instead of removing it maybe give the error unless it’s the last field of
the record and in which case can assumed to be fully defined.
No, that is too random for a language.
This change is not up for discussion as it could lead to incorrect code.

Regards,
Sven
John Doe
2018-11-14 01:05:18 UTC
Permalink
On Mon, Nov 12, 2018 at 1:51 AM Sven Barth via fpc-pascal <
Post by Sven Barth via fpc-pascal
The compiler now correctly rejects such declarations with a "Type is
not completely defined error".
Making this not work is a ridiculous removal of a feature for no logical
reason that serves no benefit to anyone whatsoever. It just makes records
less useful, and that's it.

I've already encountered several large libraries that are pretty massively
broken by this pointless change. You're very visibly just making up
arbitrary "rules" out of nowhere that certainly aren't actually defined
anywhere and implementing (or de-implementing) whatever strikes your fancy
on a given day.

Also:

On Sat, Nov 10, 2018 at 4:56 AM Sven Barth via fpc-pascal <
Post by Sven Barth via fpc-pascal
It's not possible to use typed constants as initializers for variables.
What are you talking about? Of course that's possible. People do it
literally all the time.
Sven Barth via fpc-pascal
2018-11-14 05:37:15 UTC
Permalink
Post by John Doe
On Mon, Nov 12, 2018 at 1:51 AM Sven Barth via fpc-pascal
The compiler now correctly rejects such declarations with a "Type
is not completely defined error".
Making this not work is a ridiculous removal of a feature for no
logical reason that serves no benefit to anyone whatsoever. It just
makes records less useful, and that's it.
Just to avoid any confusion: I am talking about a typed constant
declared inside a record's declaration of the same type as the record.
Constants outside a record, even inside other records work as before.
Also there can't be that many libraries affected, because this only ever
worked in trunk. In 3.0.x the compiler simply crashed when encountering
such a constant.
Post by John Doe
I've already encountered several large libraries that are pretty
massively broken by this pointless change. You're very visibly just
making up arbitrary "rules" out of nowhere that certainly aren't
actually defined anywhere and implementing (or de-implementing)
whatever strikes your fancy on a given day.
On Sat, Nov 10, 2018 at 4:56 AM Sven Barth via fpc-pascal
It's not possible to use typed constants as initializers for variables.
What are you talking about? Of course that's possible. People do it
literally all the time.
=== code begin ===

type
  TTest = record
  public
    a: LongInt;
    b: LongInt;
  public //const
    //Default: array of TTest;// = (a: 42; b: 21);
  end;

const
  Test: TTest = (a: 42; b: 21);

var
  TestVar: TTest = Test; // <<<< this fails, because typed constants
can't be used as initializers (would also be the case if Test and
TestVar had any other type; only untyped constants are supported here)

=== code end ===

Regards,
Sven
Benjamin Rosseaux
2018-11-28 19:27:22 UTC
Permalink
program Test123;
{$ifdef fpc}
{$mode delphi}
{$endif}

type
TTest = record
public
a: LongInt;
b: LongInt;
end;

TTestHelper = record helper for TTest
public
const Default: TTest = (a: 1; b: 2);
end;

var
Test: TTest;
begin
Test := TTest.Default;
end.
Should’t this work? This would be a good way to set default record values
but it doesn’t seem to be supported.
type
TMyRecord = record
public
a: integer;
b: string;
const
default: TMyRecord = (a: 100; b: 'foo');
end;
var
r: TMyRecord = TMyRecord.default;
Regards,
Ryan Joseph
_______________________________________________
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Sven Barth via fpc-pascal
2018-11-28 19:46:51 UTC
Permalink
Post by Benjamin Rosseaux
program Test123;
{$ifdef fpc}
  {$mode delphi}
{$endif}
type
  TTest = record
  public
    a: LongInt;
    b: LongInt;
  end;
  TTestHelper = record helper for TTest
  public
    const Default: TTest = (a: 1; b: 2);
  end;
var
  Test: TTest;
begin
  Test := TTest.Default;
end.
That is indeed a good idea and with the extension to allow multiple
helpers there wouldn't even be a negative impact... 🀔

Regards,
Sven
Benjamin Rosseaux
2018-11-28 20:34:47 UTC
Permalink
I'm using this solution myself for the vector and matrix data types at

https://github.com/BeRo1985/pasvulkan/blob/master/src/PasVulkan.Math.pas
https://github.com/BeRo1985/pasvulkan/blob/master/src/PasVulkan.Math.TpvVector2.Swizzle.Definitions.inc
https://github.com/BeRo1985/pasvulkan/blob/master/src/PasVulkan.Math.TpvVector2.Swizzle.Implementations.inc
https://github.com/BeRo1985/pasvulkan/blob/master/src/PasVulkan.Math.TpvVector2Helper.Swizzle.Definitions.inc
https://github.com/BeRo1985/pasvulkan/blob/master/src/PasVulkan.Math.TpvVector2Helper.Swizzle.Implementations.inc
https://github.com/BeRo1985/pasvulkan/blob/master/src/PasVulkan.Math.TpvVector3.Swizzle.Definitions.inc
https://github.com/BeRo1985/pasvulkan/blob/master/src/PasVulkan.Math.TpvVector3.Swizzle.Implementations.inc
https://github.com/BeRo1985/pasvulkan/blob/master/src/PasVulkan.Math.TpvVector3Helper.Swizzle.Definitions.inc
https://github.com/BeRo1985/pasvulkan/blob/master/src/PasVulkan.Math.TpvVector3Helper.Swizzle.Implementations.inc
https://github.com/BeRo1985/pasvulkan/blob/master/src/PasVulkan.Math.TpvVector4.Swizzle.Definitions.inc
https://github.com/BeRo1985/pasvulkan/blob/master/src/PasVulkan.Math.TpvVector4.Swizzle.Implementations.inc
https://github.com/BeRo1985/pasvulkan/blob/master/src/PasVulkan.Math.TpvVector4Helper.Swizzle.Definitions.inc
https://github.com/BeRo1985/pasvulkan/blob/master/src/PasVulkan.Math.TpvVector4Helper.Swizzle.Implementations.inc

without any bigger issues, except that the Delphi IDE has some runtime
CodeInsight record lookup issues from time to time.


On Wed, Nov 28, 2018 at 8:47 PM Sven Barth via fpc-pascal <
Post by Benjamin Rosseaux
program Test123;
{$ifdef fpc}
{$mode delphi}
{$endif}
type
TTest = record
public
a: LongInt;
b: LongInt;
end;
TTestHelper = record helper for TTest
public
const Default: TTest = (a: 1; b: 2);
end;
var
Test: TTest;
begin
Test := TTest.Default;
end.
That is indeed a good idea and with the extension to allow multiple
helpers there wouldn't even be a negative impact... 🀔
Regards,
Sven
_______________________________________________
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Ryan Joseph
2018-11-29 02:36:50 UTC
Permalink
Post by Benjamin Rosseaux
TTestHelper = record helper for TTest
public
const Default: TTest = (a: 1; b: 2);
end;
I didn’t even know you could add consts to record helpers. That’s good to know, thanks.

Multi scoped helpers will make this a safe solution which you don’t have to worry about being overwritten in other units. Hopefully I can submit a patch for the trunk soon.

Regards,
Ryan Joseph

_______________________________________________
fpc-pascal maillist - fpc-***@lists.freepascal.org
http://lists.freepascal.org/cgi-bin/mailma

Continue reading on narkive:
Loading...