Sign in Join

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

Mailing lists / fpc-pascal / 2018-08

why can't we define class operator for old fashion object type, but ok for 'advanced record' type?

19 messages · 7 people · –

Reply by email Subscribe to this list Your subscription

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

Dennis

I was trying to use a generic class TDictionary<T>  with type T. This class has a method that compares a variable of T with another one.

When I specialize a class using this TDictionary with a type:

TSecurity = object
  ....
end;

e.g. TNewDict = class(TDictionary<String, TSecurity>);

it raise a compiler complaining that my TSecurity type has no operator = defined.

But when I try to add like this:

TSecurity = object
   ....
class operator =  (constref aLeft, aRight: TSecurity ): Boolean;
//<---compiler Error: Procedure or Function expected
end;

However, the following is OK
{$MODESWITCH advancedrecords}
TSecurity = record
  ....
class operator =  (constref aLeft, aRight: TSecurity ): Boolean; //<---OK

end;

Why class operator is accepted for advanced records but not old fashion object???

I cannot use advance record because it does have inherit methods. I need method inheritance for my object.

Dennis

Reply by email

Michael Van Canneyt
to Dennis
Dennis wrote 23 lines
I was trying to use a generic class TDictionary<T>  with type T. This class has a method that compares a variable of T with another one. When I specialize a class using this TDictionary with a type: TSecurity = object   .... end; e.g. TNewDict = class(TDictionary<String, TSecurity>); it raise a compiler complaining that my TSecurity type has no operator = defined. But when I try to add like this: TSecurity = object   .... class operator =  (constref aLeft, aRight: TSecurity ): Boolean; //<---compiler Error: Procedure or Function expected end;

Did you try creating an "old-fashioned" = operator ?

Something like

Operator = (l,r : TSecurity) z : boolean;
begin
   // compare here
end;

Michael.

Reply by email

Dennis
to Michael Van Canneyt
Michael Van Canneyt wrote 38 lines
On Wed, 15 Aug 2018, Dennis wrote: > I was trying to use a generic class TDictionary<T>  with type T. This > class has a method that compares a variable of T with another one. > > When I specialize a class using this TDictionary with a type: > > TSecurity = object >   .... > end; > > > e.g. TNewDict = class(TDictionary<String, TSecurity>); > > it raise a compiler complaining that my TSecurity type has no > operator = defined. > > But when I try to add like this: > > TSecurity = object >   .... > class operator =  (constref aLeft, aRight: TSecurity ): Boolean; > //<---compiler Error: Procedure or Function expected > > end; Did you try creating an "old-fashioned" = operator ? Something like Operator = (l,r : TSecurity) z : boolean; begin   // compare here end;

Just tried.
It complained:   Fatal: Syntax error, "IMPLEMENTATION" expected but "identifier OPERATOR" found

Dennis

Reply by email

Michael Van Canneyt
to Dennis
Dennis wrote 45 lines
Michael Van Canneyt wrote: > > > On Wed, 15 Aug 2018, Dennis wrote: > >> I was trying to use a generic class TDictionary<T>  with type T. This >> class has a method that compares a variable of T with another one. >> >> When I specialize a class using this TDictionary with a type: >> >> TSecurity = object >>   .... >> end; >> >> >> e.g. TNewDict = class(TDictionary<String, TSecurity>); >> >> it raise a compiler complaining that my TSecurity type has no >> operator = defined. >> >> But when I try to add like this: >> >> TSecurity = object >>   .... >> class operator =  (constref aLeft, aRight: TSecurity ): Boolean; >> //<---compiler Error: Procedure or Function expected >> >> end; > > Did you try creating an "old-fashioned" = operator ? > > Something like > > Operator = (l,r : TSecurity) z : boolean; > > begin >   // compare here > end; > Just tried. It complained:   Fatal: Syntax error, "IMPLEMENTATION" expected but "identifier OPERATOR" found

Following works here:

Prograp testo;
Type
   TSecurity = Object
     a,b : Integer;
   end;
Operator = (l,r : TSecurity) z : boolean;
begin
   Z:=(l.a=r.a) and (L.b=r.b);
end;
begin
end.

But maybe you are using mode delphi ? If so, try separating out the object definition in a separate unit which is not compiled in delphi mode.

Michael.

Reply by email

Sven Barth
to Michael Van Canneyt
Michael Van Canneyt wrote 72 lines
On Wed, 15 Aug 2018, Dennis wrote: > > > Michael Van Canneyt wrote: >> >> >> On Wed, 15 Aug 2018, Dennis wrote: >> >>> I was trying to use a generic class TDictionary<T>  with type T. >>> This class has a method that compares a variable of T with another >>> one. >>> >>> When I specialize a class using this TDictionary with a type: >>> >>> TSecurity = object >>>   .... >>> end; >>> >>> >>> e.g. TNewDict = class(TDictionary<String, TSecurity>); >>> >>> it raise a compiler complaining that my TSecurity type has no >>> operator = defined. >>> >>> But when I try to add like this: >>> >>> TSecurity = object >>>   .... >>> class operator =  (constref aLeft, aRight: TSecurity ): Boolean; >>> //<---compiler Error: Procedure or Function expected >>> >>> end; >> >> Did you try creating an "old-fashioned" = operator ? >> >> Something like >> >> Operator = (l,r : TSecurity) z : boolean; >> >> begin >>   // compare here >> end; >> > > Just tried. > It complained:   Fatal: Syntax error, "IMPLEMENTATION" expected but > "identifier OPERATOR" found Following works here: Prograp testo; Type   TSecurity = Object     a,b : Integer;   end; Operator = (l,r : TSecurity) z : boolean; begin   Z:=(l.a=r.a) and (L.b=r.b); end; begin end. But maybe you are using mode delphi ? If so, try separating out the object definition in a separate unit which is not compiled in delphi mode.

A global operator won't help at all as (currently) the operator won't be visible during the specialization. Only if the operator is visible during the *generic's* declaration it would be picked up.

Regards,
Sven

Reply by email

Michael Van Canneyt
to Sven Barth: A global operator won't help at all as (currently) the operator won't be visible during…
Sven Barth wrote 7 lines
> > But maybe you are using mode delphi ? If so, try separating out the > object > definition in a separate unit which is not compiled in delphi mode. A global operator won't help at all as (currently) the operator won't be visible during the specialization. Only if the operator is visible during the *generic's* declaration it would be picked up.

That is contrary to the class operator, which is also only visible during specialization, after all.

Is there a reason for this behaviour ?

Michael.

Reply by email

Sven Barth
to Michael Van Canneyt
Michael Van Canneyt wrote 16 lines
On Wed, 15 Aug 2018, Sven Barth via fpc-pascal wrote: >> >> But maybe you are using mode delphi ? If so, try separating out the >> object >> definition in a separate unit which is not compiled in delphi mode. > A global operator won't help at all as (currently) the operator won't > be visible during the specialization. Only if the operator is visible > during the *generic's* declaration it would be picked up. That is contrary to the class operator, which is also only visible during specialization, after all. Is there a reason for this behaviour ?

The operator of a record is visible together with the record, however a global operator is not. When specializing the unit scope of the declaration of the *generic* is restored thus no helpers or global operators of the current scope are visible except they are part of the type parameter.
I do want to try to change this in the future, but I need to be careful to not open a different can of worms (as Delphi doesn't do it this way).

Regards,
Sven

Reply by email

Dennis Poon
to Sven Barth: Because objects are not records. Internally they are handled more closely to classes than…
Sven Barth wrote 6 lines
Am 15.08.2018 um 10:59 schrieb Dennis: > Why class operator is accepted for advanced records but not old > fashion object??? Because objects are not records. Internally they are handled more closely to classes than records.

Would it be too hard to also implement class operators for old fashion objects?  That will be very  nice.

Dennis

Reply by email

Michael Van Canneyt
to Sven Barth: The operator of a record is visible together with the record, however a global operator…
Show quoted text 25 lines
Am 15.08.2018 um 17:29 schrieb Michael Van Canneyt: > > > On Wed, 15 Aug 2018, Sven Barth via fpc-pascal wrote: > >>> >>> But maybe you are using mode delphi ? If so, try separating out the >>> object >>> definition in a separate unit which is not compiled in delphi mode. >> A global operator won't help at all as (currently) the operator won't >> be visible during the specialization. Only if the operator is visible >> during the *generic's* declaration it would be picked up. > > That is contrary to the class operator, which is also only visible > during > specialization, after all. > > Is there a reason for this behaviour ? The operator of a record is visible together with the record, however a global operator is not. When specializing the unit scope of the declaration of the *generic* is restored thus no helpers or global operators of the current scope are visible except they are part of the type parameter. I do want to try to change this in the future, but I need to be careful to not open a different can of worms (as Delphi doesn't do it this way).

Purely reasoning in terms of data structures:

I would think you 'attach' operators to the type for which they are defined ? If the 'attach' link structure contains the unit in which the operator definition resides, you can check whether this unit is visible, and if yes, the operator is 'usable'.

Michael.

Reply by email

Sven Barth
to Michael Van Canneyt
Michael Van Canneyt wrote 28 lines
> Am 15.08.2018 um 17:29 schrieb Michael Van Canneyt: >> >> On Wed, 15 Aug 2018, Sven Barth via fpc-pascal wrote: >> >>>> But maybe you are using mode delphi ? If so, try separating out the >>>> object >>>> definition in a separate unit which is not compiled in delphi mode. >>> A global operator won't help at all as (currently) the operator won't >>> be visible during the specialization. Only if the operator is visible >>> during the *generic's* declaration it would be picked up. >> That is contrary to the class operator, which is also only visible >> during >> specialization, after all. >> >> Is there a reason for this behaviour ? > The operator of a record is visible together with the record, however a > global operator is not. When specializing the unit scope of the > declaration of the *generic* is restored thus no helpers or global > operators of the current scope are visible except they are part of the > type parameter. > I do want to try to change this in the future, but I need to be careful > to not open a different can of worms (as Delphi doesn't do it this way). Purely reasoning in terms of data structures: I would think you 'attach' operators to the type for which they are defined ? If the 'attach' link structure contains the unit in which the operator definition resides, you can check whether this unit is visible, and if yes, the operator is 'usable'.

No, they are not attached. Remember that global operators don't need to reside in the same unit as the type they're operating on. And it would be rather useless time to search for existing operator overloads for any type when the program uses none of them in the end. Thus the compiler looks for operators on the fly once it encounters the use of one, it's just like looking for method calls with a slightly different syntax. The scope of a structured type is always looked in first and then all units in the scope are searched for global operators.

Regards,
Sven

Reply by email

Sven Barth
to Dennis Poon: Would it be too hard to also implement class operators for old fashion objects?  That…
Dennis Poon wrote 11 lines
Sven Barth via fpc-pascal wrote: > Am 15.08.2018 um 10:59 schrieb Dennis: >> Why class operator is accepted for advanced records but not old >> fashion object??? > Because objects are not records. Internally they are handled more > closely to classes than records. > Would it be too hard to also implement class operators for old fashion objects?  That will be very  nice.

It shouldn't be hard. Feel free to provide a patch together with some tests and it will be taken under consideration.

Regards,
Sven

Reply by email

Ryan Joseph
to Sven Barth
On Aug 16, 2018, at 8:55 AM, Sven Barth via fpc-pascal wrote: It shouldn't be hard. Feel free to provide a patch together with some tests and it will be taken under consideration.

So the reason that objects/classes in FPC don’t have operators in the class (like advanced records) is for Delphi compatibility? That would be great if operators were unified across records/classes.

Regards,
Ryan Joseph

Reply by email

Maciej Izak
to Ryan Joseph

2018-08-17 17:48 GMT+02:00 Ryan Joseph :

So the reason that objects/classes in FPC don’t have operators in the class (like advanced records) is for Delphi compatibility? That would be great if operators were unified across records/classes.

In Delphi (NEXTGEN for mobile platforms and Linux) is possible to use class operators for classes (in NEXTGEN classes are managed by ARC).

More info:

http://blog.marcocantu.com/blog/class_operators_delphi.html

the existence of class operators for classes in NEXTGEN is presented as "a side effect of the new Automatic Reference Counting support"

Best regards, Maciej Izak

Reply by email

Sven Barth
to Ryan Joseph: So the reason that objects/classes in FPC don’t have operators in the class (like…

Ryan Joseph schrieb am Fr., 17. Aug. 2018,
18:22:

Show quoted text 12 lines
> On Aug 16, 2018, at 8:55 AM, Sven Barth via fpc-pascal < > wrote: > > It shouldn't be hard. Feel free to provide a patch together with some tests and it will be taken under consideration. So the reason that objects/classes in FPC don’t have operators in the class (like advanced records) is for Delphi compatibility? That would be great if operators were unified across records/classes.

Not entirely. In Delphi objects are deprecated, so as long as old code keeps compiling and running we can mess with them.

However for classes there is the problem of temporary variables. Take a := b + c + d. That is essentially compiled as t := b + c; a := t + d. The compiler does not know whether the operator creates an instance or not (yes, there are circumstances when it can know that, but for the general case it can't) and thus this would potentially lead to memory leaks.

Thus automatic reference counting or garbage collection or something like that is required for this to work nicely.

Regards,
Sven

Reply by email

Michael Van Canneyt
to Bo Berglund
Bo Berglund wrote 8 lines
On Sat, 18 Aug 2018 03:19:55 +0200, Sven Barth via fpc-pascal wrote: > In Delphi objects are deprecated Huh? ObjectPascal deprecating objects? Sounds far-fetched.

Old-style TP Objects are deprecated, but classes are not.

Michael.

Reply by email

Ryan Joseph
to Sven Barth: Ryan Joseph schrieb am Fr., 17. Aug. 2018, 18:22: Not entirely. In Delphi objects are…
On Aug 17, 2018, at 7:19 PM, Sven Barth via fpc-pascal wrote: However for classes there is the problem of temporary variables. Take a := b + c + d. That is essentially compiled as t := b + c; a := t + d. The compiler does not know whether the operator creates an instance or not (yes, there are circumstances when it can know that, but for the general case it can't) and thus this would potentially lead to memory leaks.

I’m must be confused because classes already have operator overloads, they’re just in global scope outside of the class itself. Don’t all the same rules apply if the syntax is put inside the class (like in records) just the scope rules change?

Regards,
Ryan Joseph

Reply by email

Sven Barth
to Ryan Joseph

Ryan Joseph schrieb am Sa., 18. Aug. 2018,
19:38:

Show quoted text 17 lines
> On Aug 17, 2018, at 7:19 PM, Sven Barth via fpc-pascal < > wrote: > > However for classes there is the problem of temporary variables. Take a := b + c + d. That is essentially compiled as t := b + c; a := t + d. The compiler does not know whether the operator creates an instance or not (yes, there are circumstances when it can know that, but for the general case it can't) and thus this would potentially lead to memory leaks. > I’m must be confused because classes already have operator overloads, they’re just in global scope outside of the class itself. Don’t all the same rules apply if the syntax is put inside the class (like in records) just the scope rules change?

Delphi does not have global operator overloads and in FPC the problem I mentioned indeed happens with global overloads. It's just that not many people use global overloads for classes (especially now that generics are used more).

Regards,
Sven

Reply by email