Record operator for assignment

classic Classic list List threaded Threaded
18 messages Options
Reply | Threaded
Open this post in threaded view
|

Record operator for assignment

Ryan Joseph
Instead of making constructors and doing busy work It would be nice if Free Pascal could let you assign records outside of type blocks like:

rec := (x: 0; y: 0; z: 0);

Why isn’t this possible btw? I saw some C++ code do this and it seems like an obvious solution that should have existed 20 years ago. The feature exists for type blocks so why not just enable it for other parts of code?

I had another idea to make this a little simpler by using open arrays and operator overloading. The compiler doesn’t permit this however. Is it a bug, my code or just a limitation?

============


type
        TMyRec = record
                x, y, z: integer;
                class operator Explicit(v: array of integer): TMyRec;
        end;

class operator TMyRec.Explicit(v: array of integer): TMyRec;
begin
        result.x := v[0];
        result.y := v[1];
        result.z := v[2];
end;


var
        rec: TMyRec;

rec := TMyRec([1, 2, 3]); // Illegal type conversion: "Set Of Byte" to "TMyRec"

Regards,
        Ryan Joseph

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Record operator for assignment

LacaK

> Instead of making constructors and doing busy work It would be nice if Free Pascal could let you assign records outside of type blocks like:
>
> rec := (x: 0; y: 0; z: 0);
you can workaround this by using typed constant for instance. Something
like:

const
   DEFAULT_REC: TMyRec = (x: 0; y: 0; z: 0 );
var
   rec: TMyRec;
begin
   rec := DEFAULT_REC; // or rec := Default(TMyRec) if you want zeroes
   ...

L.

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Record operator for assignment

Ryan Joseph

> On Apr 28, 2017, at 12:21 PM, LacaK <[hidden email]> wrote:
>
> you can workaround this by using typed constant for instance. Something like:
>
> const
>  DEFAULT_REC: TMyRec = (x: 0; y: 0; z: 0 );
> var
>  rec: TMyRec;
> begin
>  rec := DEFAULT_REC; // or rec := Default(TMyRec) if you want zeroes
>  ...
>
> L.

Run time is the problem though. If the compiler knows how to define a record using that syntax you should be able to do

rec := (x: a; y: b; z: c);

instead of mucking around with constructors which do basically the same thing but with boiler plate code. The syntax for a default constructor already exists in the language but it’s not implemented outside of type declarations for some reason.

Regards,
        Ryan Joseph

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Record operator for assignment

Free Pascal - General mailing list
In reply to this post by Ryan Joseph

Am 28.04.2017 06:06 schrieb "Ryan Joseph" <[hidden email]>:
>
> Instead of making constructors and doing busy work It would be nice if Free Pascal could let you assign records outside of type blocks like:
>
> rec := (x: 0; y: 0; z: 0);
>
> Why isn’t this possible btw? I saw some C++ code do this and it seems like an obvious solution that should have existed 20 years ago. The feature exists for type blocks so why not just enable it for other parts of code?

It would introduce an ambiguity as "(x" could also complete to other expressions (e.g. "(x + y) * 2" or even merely "(x)"). Especially older Pascal compilers were geared towards the simplicity of the language and thus they didn't add it. For FPC it simply never came up.

> I had another idea to make this a little simpler by using open arrays and operator overloading. The compiler doesn’t permit this however. Is it a bug, my code or just a limitation?
>
> ============
>
>
> type
>         TMyRec = record
>                 x, y, z: integer;
>                 class operator Explicit(v: array of integer): TMyRec;
>         end;
>
> class operator TMyRec.Explicit(v: array of integer): TMyRec;
> begin
>         result.x := v[0];
>         result.y := v[1];
>         result.z := v[2];
> end;
>
>
> var
>         rec: TMyRec;
>
> rec := TMyRec([1, 2, 3]); // Illegal type conversion: "Set Of Byte" to "TMyRec"

The compiler currently prefers to cast array constructors towards sets, especially if they contain values that could be expressed as a set. That will change once proper support for array constructors is added. Though I don't know whether this would work then ;)

Regards,
Sven


_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Record operator for assignment

Ryan Joseph

> On Apr 28, 2017, at 12:43 PM, Sven Barth via fpc-pascal <[hidden email]> wrote:
>
> It would introduce an ambiguity as "(x" could also complete to other expressions (e.g. "(x + y) * 2" or even merely "(x)"). Especially older Pascal compilers were geared towards the simplicity of the language and thus they didn't add it. For FPC it simply never came up.

I never thought about it either until I saw some c++ code doing it. Despite having overlooked it, it’s basically a built in record constructor that’s been in the language since forever. First it was making functions that paired with records and now it’s constructors and "advanced record syntax" when the more obvious and simpler solution was there all along. Maybe I’m crazy though. ;)

You mean like:

rec := (x: (x + y) * 2; y: 0; z: 0);

Why can’t everything between : and ; just be treated like a normal assignment? “x” is already defined but it’s just a label and not part of the assignment.

>
> The compiler currently prefers to cast array constructors towards sets, especially if they contain values that could be expressed as a set. That will change once proper support for array constructors is added. Though I don't know whether this would work then ;)

Huh, that syntax works in constructors, just not in the operator overloading. Anyways I guess I’ll just assume that’s not implemented behavior.

Thanks.

Regards,
        Ryan Joseph

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Record operator for assignment

Free Pascal - General mailing list
On 28.04.2017 08:01, Ryan Joseph wrote:

>
>> On Apr 28, 2017, at 12:43 PM, Sven Barth via fpc-pascal <[hidden email]> wrote:
>>
>> It would introduce an ambiguity as "(x" could also complete to other expressions (e.g. "(x + y) * 2" or even merely "(x)"). Especially older Pascal compilers were geared towards the simplicity of the language and thus they didn't add it. For FPC it simply never came up.
>
> I never thought about it either until I saw some c++ code doing it. Despite having overlooked it, it’s basically a built in record constructor that’s been in the language since forever. First it was making functions that paired with records and now it’s constructors and "advanced record syntax" when the more obvious and simpler solution was there all along. Maybe I’m crazy though. ;)
>
> You mean like:
>
> rec := (x: (x + y) * 2; y: 0; z: 0);

No, I mean

rec := (x + y) * 2;

The compiler has to differentiate these two.

> Why can’t everything between : and ; just be treated like a normal assignment? “x” is already defined but it’s just a label and not part of the assignment.

And that's another point. The compiler does not know what "x", "y" and
"z" are, cause it doesn't care about the left hand side of the
assignment until *after* the right hand side is parsed (in a var/const
section it knows the type; that's a different situation).
So a different syntax would be needed that would allow the compiler to
know that it's parsing a specific record type.

>>
>> The compiler currently prefers to cast array constructors towards sets, especially if they contain values that could be expressed as a set. That will change once proper support for array constructors is added. Though I don't know whether this would work then ;)
>
> Huh, that syntax works in constructors, just not in the operator overloading. Anyways I guess I’ll just assume that’s not implemented behavior.

Because in that case it knows that it's a parameter and handles that
differently. A type conversion is a different case.

Regards,
Sven

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Record operator for assignment

Ryan Joseph

> On Apr 28, 2017, at 1:06 PM, Sven Barth via fpc-pascal <[hidden email]> wrote:
>
> No, I mean
>
> rec := (x + y) * 2;
>
> The compiler has to differentiate these two.

I see. It’s the parenthesis that are problematic. I guess the solution would be curly brackets:

rec := {x: 1; y: 2; z: 1}

or some magic function like writeln:

rec := TMyRec(x: 1; y: 2; z: 1)

rec := @(x: 1; y: 2; z: 1)

etc…

Anyway it could be achieved that would be nice to have a built in constructor for records on the language level.



Regards,
        Ryan Joseph

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Record operator for assignment

LacaK

> I see. It’s the parenthesis that are problematic. I guess the solution would be curly brackets:
>
> rec := {x: 1; y: 2; z: 1}
>
> or some magic function like writeln:
>
> rec := TMyRec(x: 1; y: 2; z: 1)
>
> rec := @(x: 1; y: 2; z: 1)
>
> etc…
or use like dynamic array constructor:
(MyArr := TMyDynArrType.Create(value1, value2) );)

rec := TMyRec.Create(x: 1; y: 2; z: 1);

;-)
-Laco.

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Record operator for assignment

Free Pascal - General mailing list
In reply to this post by Ryan Joseph

Am 28.04.2017 09:23 schrieb "Ryan Joseph" <[hidden email]>:
>
>
> > On Apr 28, 2017, at 1:06 PM, Sven Barth via fpc-pascal <[hidden email]> wrote:
> >
> > No, I mean
> >
> > rec := (x + y) * 2;
> >
> > The compiler has to differentiate these two.
>
> I see. It’s the parenthesis that are problematic. I guess the solution would be curly brackets:
>
> rec := {x: 1; y: 2; z: 1}

Curly brackets are comments!

> or some magic function like writeln:
>
> rec := TMyRec(x: 1; y: 2; z: 1)

That could be a possibility as the compiler could then correctly handle the field names, however it would have an ambiguity with typecasts until the colon.
Though that would be solvable...

> rec := @(x: 1; y: 2; z: 1)

@ would be nonsense as that would denote a pointer.

> etc…
>
> Anyway it could be achieved that would be nice to have a built in constructor for records on the language level.
>

Well, feel free to develop a patch, maybe it'll be accepted. I have other fish to fry in the meantime.

Regards,
Sven


_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Record operator for assignment

Mark Morgan Lloyd-5
In reply to this post by Ryan Joseph
On 28/04/17 04:30, Ryan Joseph wrote:
> Instead of making constructors and doing busy work It would be nice if Free Pascal could let you assign records outside of type blocks like:
> rec := (x: 0; y: 0; z: 0);
> Why isn’t this possible btw? I saw some C++ code do this and it seems like an obvious solution that should have existed 20 years ago. The feature exists for type blocks so why not just enable it for other parts of code?
> I had another idea to make this a little simpler by using open arrays and operator overloading. The compiler doesn’t permit this however. Is it a bug, my code or just a limitation?

Curiously, I was up against exactly the same thing yesterday when
setting up an array for GetLongOpts() and a table for tokenising some
other text elements.

I ended up using a dynamic array and overloading + for the first of
those since it allowed me to do

   with option do begin
     name := 'block';
     value := name[1]   <===
   end;
   theOpts += option;

which wouldn't be available at compilation time, and also since
build-time directives could easily include/exclude options. For the
other one I used an array of records.

The problem with arrays of records as I see it is that the number of
elements has to be predefined:

const   TopMatchItem= 10;

type    TMatchItem= record
                       name: string;
                       field: TCSVField
                     end;
         TAMatchItem= array[0..TopMatchItem] of TMatchItem;

const   matchItems: TAMatchItem= ((name: ''; field: CSVBad),
                       (name: 'block'; field: CSVBlock),
..

Or from the FPC compiler itself:

   ttokenarray=array[ttoken] of tokenrec;
   ptokenarray=^ttokenarray;
..

const
   arraytokeninfo : ttokenarray =(
       (str:''              ;special:true ;keyword:[m_none];op:NOTOKEN),
..

Is there any way that the length of an array being used for that sort of
job can be defined by what's put into it, rather than having to be
predefined?

--
Mark Morgan Lloyd
markMLl .AT. telemetry.co .DOT. uk

[Opinions above are the author's, not those of his employers or colleagues]
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Record operator for assignment

Free Pascal - General mailing list

Am 28.04.2017 14:09 schrieb "Mark Morgan Lloyd" <[hidden email]>:
> Is there any way that the length of an array being used for that sort of job can be defined by what's put into it, rather than having to be predefined?

No, there is not. Though I already had the idea that such preinitialized dynamic arrays (because that's what they'd need to be for consistency) could be implemented. Alas that's another small point on my huge ToDo list... :/

Regards,
Sven


_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Record operator for assignment

Ryan Joseph
In reply to this post by Free Pascal - General mailing list

> On Apr 28, 2017, at 3:51 PM, Ryan Joseph <[hidden email]> wrote:
>
> I almost struck out there. ;) There’s at least a possibility for anyone interested. A few years ago I looked at the compiler source and decided it was beyond me to even understand the code base well enough to do anything. How do people get into this any ways? The learning curve is so steep it’s a miracle anyone is able to contribute.

I was looking at a Swift language guide (Apple’s new language) and they have this exact same syntax for initializing structs (like a default constructor that Pascal is missing).

From their guide “vga" is a struct with 2 fields: width and height. Swift uses labels in functions (like Objective-C) but the end result is that it looks identical to the Pascal syntax for defining constant records.

======

All structures have an automatically-generated memberwise initializer, which you can use to initialize the member properties of new structure instances. Initial values for the properties of the new instance can be passed to the memberwise initializer by name:

var vga = Resolution(width: 640, height: 480)

Regards,
        Ryan Joseph

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Record operator for assignment

Marco van de Voort
In our previous episode, Ryan Joseph said:
> All structures have an automatically-generated memberwise initializer, which you can use to initialize the member properties of new structure instances. Initial values for the properties of the new instance can be passed to the memberwise initializer by name:
>
> var vga = Resolution(width: 640, height: 480)

Scripting languages often already by default initialize a datatructure, and
then such language constructs only performs additional initialization.

Pascal and similar lowlevel languages don't by default initialize them, and then whole initialization is
more logical.
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Record operator for assignment

Ryan Joseph

> On May 4, 2017, at 4:27 PM, Marco van de Voort <[hidden email]> wrote:
>
> Scripting languages often already by default initialize a datatructure, and
> then such language constructs only performs additional initialization.
>
> Pascal and similar lowlevel languages don't by default initialize them, and then whole initialization is
> more logical.

It’s optional and basically just a default constructor which takes all fields as it’s arguments. You don’t need to call it if you don’t want. Swift is compiled afaik but it does way more behind the scenes than I’d like Pascal to do and does behave like a scripting language in many ways (inferred types for example). That being said Pascal records should still have a default constructor since this is a pattern repeated extremely frequently.

Regards,
        Ryan Joseph

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Record operator for assignment

Free Pascal - General mailing list
In reply to this post by Ryan Joseph

Am 04.05.2017 10:37 schrieb "Ryan Joseph" <[hidden email]>:
>
>
> > On Apr 28, 2017, at 3:51 PM, Ryan Joseph <[hidden email]> wrote:
> >
> > I almost struck out there. ;) There’s at least a possibility for anyone interested. A few years ago I looked at the compiler source and decided it was beyond me to even understand the code base well enough to do anything. How do people get into this any ways? The learning curve is so steep it’s a miracle anyone is able to contribute.

One starts with something simple and works one's way up. My first real compiler contribution were if I remember correctly class helpers. And at that time I knew next to nothing about the compiler and thus had to learn by doing and debugging.

Regards,
Sven


_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Record operator for assignment

noreply
In reply to this post by Ryan Joseph
On 2017-04-28 01:01, Ryan Joseph wrote:

>> On Apr 28, 2017, at 12:43 PM, Sven Barth via fpc-pascal
>> <[hidden email]> wrote:
>>
>> It would introduce an ambiguity as "(x" could also complete to other
>> expressions (e.g. "(x + y) * 2" or even merely "(x)"). Especially
>> older Pascal compilers were geared towards the simplicity of the
>> language and thus they didn't add it. For FPC it simply never came up.
>
> I never thought about it either until I saw some c++ code doing it.
> Despite having overlooked it, it’s basically a built in record
> constructor that’s been in the language since forever.

You can also look into GoLang for struct ideas, as golang is simpler
than C++

> rec := (x: (x + y) * 2; y: 0; z: 0);
>
> Why can’t everything between : and ; just be treated like a normal
> assignment? “x” is already defined but it’s just a label and not part
> of the assignment.
>

It's always easier said than done, to say "Why can't" and then have to
write the actual parser code to do it ;-)

I think fpc is based on wirth's simplicity, and even wirth's languages
probably did not have the ability to setup a record initially with
default record as another poster said. I do like this feature a lot ,
but can see why a minimalist like worth would avoid it.

It's similar to this feature:

x,y,z := 1, 12, 7

It's neat to be able to assign multiple variables on a single line. But
necessary? mandatory?
Again, could look into golang for ideas.. may have something like it
too, without becoming a large C++ mammoth.

In fact that's how golang's error checking works.
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Record operator for assignment

Ryan Joseph

> On May 8, 2017, at 10:47 AM, [hidden email] wrote:
>
> It's always easier said than done, to say "Why can't" and then have to write the actual parser code to do it ;-)

Yes indeed. I just looked over svn to see where Sven added his new dynamic array initializers and I’m still totally confused. It’s really a miracle anyone is able to contribute to such a large code base without any documentation.

Since we have record constructors and static class functions for records now it seems like the language is going out of its way to provide the simplest solution.

Yeah Golang has the same thing: c := Circle{x: 0, y: 0, r: 5} and basically the same syntax as Pascal or Swift.

Regards,
        Ryan Joseph

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Record operator for assignment

Jürgen Hestermann
In reply to this post by noreply
Am 2017-05-08 um 05:47 schrieb [hidden email]:
 > It's similar to this feature:
 > x,y,z := 1, 12, 7
 > It's neat to be able to assign multiple variables on a single line. But necessary? mandatory?

It's not even neat.
It would bloat the Pascal language unneccesarily (as many other additions have done in the past).

I definitely prefer

x :=  1;
y := 12;
z :=  7;

where I see much better which value is assigned to which variable.
Look at this:

a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u := 3,5,1,7,33,82,7,14,9,0,-1,1,13,14,17,8,2,9,15,88,62;

would that be readable code?

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal