Discussion:
[fpc-pascal] why can't we define class operator for old fashion object type, but ok for 'advanced record' type?
Dennis
2018-08-15 08:59:35 UTC
Permalink
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
_______________________________________________
fpc-pascal maillist - fpc-***@lists.freepascal.org
http://lists.freepascal.org/cgi-bin/mailm
Michael Van Canneyt
2018-08-15 09:05:38 UTC
Permalink
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.
TSecurity = object
  ....
end;
e.g. TNewDict = class(TDictionary<String, TSecurity>);
it raise a compiler complaining that my TSecurity type has no operator =
defined.
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.
Dennis
2018-08-15 09:12:14 UTC
Permalink
Post by Michael Van Canneyt
Post by 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.
TSecurity = object
  ....
end;
e.g. TNewDict = class(TDictionary<String, TSecurity>);
it raise a compiler complaining that my TSecurity type has no
operator = defined.
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

_______________________________________________
fpc-pascal maillist - fpc-***@lists.freepascal.org
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc
Michael Van Canneyt
2018-08-15 09:17:56 UTC
Permalink
Post by Dennis
Post by Michael Van Canneyt
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.
TSecurity = object
  ....
end;
e.g. TNewDict = class(TDictionary<String, TSecurity>);
it raise a compiler complaining that my TSecurity type has no
operator = defined.
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.
Sven Barth via fpc-pascal
2018-08-15 11:46:00 UTC
Permalink
Post by Michael Van Canneyt
Post by Dennis
Post by Michael Van Canneyt
Post by 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.
TSecurity = object
  ....
end;
e.g. TNewDict = class(TDictionary<String, TSecurity>);
it raise a compiler complaining that my TSecurity type has no
operator = defined.
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
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
_______________________________________________
fpc-pascal maillist - fpc-***@lists.freepascal.org
http://lists.freep
Michael Van Canneyt
2018-08-15 15:29:24 UTC
Permalink
Post by Sven Barth via fpc-pascal
Post by Michael Van Canneyt
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.
_______________________________________________
fpc-pascal maillist - fpc-***@lists.freepascal.org
http://l
Sven Barth via fpc-pascal
2018-08-16 08:28:05 UTC
Permalink
Post by Michael Van Canneyt
Post by Sven Barth via fpc-pascal
Post by Michael Van Canneyt
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
_______________________________________________
fpc-pascal maillist - fpc-***@lists.freepascal.org
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pas
Michael Van Canneyt
2018-08-16 10:47:02 UTC
Permalink
Post by Sven Barth via fpc-pascal
Post by Michael Van Canneyt
Post by Sven Barth via fpc-pascal
Post by Michael Van Canneyt
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.


_______________________________________________
fpc-pascal maillist - fpc-***@lists.freepascal.org
http://lists.freepascal.
Sven Barth via fpc-pascal
2018-08-16 14:50:45 UTC
Permalink
Post by Michael Van Canneyt
Post by Sven Barth via fpc-pascal
Post by Michael Van Canneyt
Post by Sven Barth via fpc-pascal
Post by Michael Van Canneyt
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).
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
_______________________________________________
fpc-pascal maillist - fpc-***@lists.freepascal.org
http://lists.freep
Sven Barth via fpc-pascal
2018-08-15 11:47:15 UTC
Permalink
Post by 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.

Regards,
Sven
_______________________________________________
fpc-pascal maillist - fpc-***@lists.freepascal.org
http://lists.freepascal.org/cgi-bin/mailman/listinfo/f
Dennis Poon
2018-08-16 10:23:05 UTC
Permalink
Post by Sven Barth via fpc-pascal
Post by 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

_______________________________________________
fpc-pascal maillist - fpc-***@lists.freepascal.org
http://lists.freepas
Sven Barth via fpc-pascal
2018-08-16 14:55:11 UTC
Permalink
Post by Dennis Poon
Post by Sven Barth via fpc-pascal
Post by 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
_______________________________________________
fpc-pascal maillist - fpc-***@lists.freepascal.org
http://
Ryan Joseph
2018-08-17 15:48:31 UTC
Permalink
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

_______________________________________________
fpc-pascal maillist - fpc-***@lists.freepascal.org
http://lists.free
Maciej Izak
2018-08-17 20:54:06 UTC
Permalink
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
Sven Barth via fpc-pascal
2018-08-18 01:19:55 UTC
Permalink
Post by Sven Barth via fpc-pascal
On Aug 16, 2018, at 8:55 AM, Sven Barth via fpc-pascal <
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
Bo Berglund
2018-08-18 05:52:09 UTC
Permalink
On Sat, 18 Aug 2018 03:19:55 +0200, Sven Barth via fpc-pascal
Post by Sven Barth via fpc-pascal
In Delphi objects are deprecated
Huh?
ObjectPascal deprecating objects?
Sounds far-fetched.
--
Bo Berglund
Developer in Sweden

_______________________________________________
fpc-pascal maillist - fpc-***@lists.freepascal.org
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-p
Michael Van Canneyt
2018-08-18 06:49:09 UTC
Permalink
Post by Bo Berglund
On Sat, 18 Aug 2018 03:19:55 +0200, Sven Barth via fpc-pascal
Post by Sven Barth via fpc-pascal
In Delphi objects are deprecated
Huh?
ObjectPascal deprecating objects?
Sounds far-fetched.
Old-style TP Objects are deprecated, but classes are not.

Michael.
_______________________________________________
fpc-pascal maillist - fpc-***@lists.freepascal.org
http://lists.freepascal.org/
Ryan Joseph
2018-08-18 17:37:46 UTC
Permalink
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

_______________________________________________
fpc-pascal maillist - fpc-***@lists.freepascal.org
http://l
Sven Barth via fpc-pascal
2018-08-19 08:11:53 UTC
Permalink
On Aug 17, 2018, at 7:19 PM, Sven Barth via fpc-pascal <
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
Loading...