Re: [Lazarus] global operator overloading
On 02/26/2013 03:07 PM, Sven Barth wrote: The critical difference between records and classes besides the ability of records to reside on the stack is that they don't allow inheritance and they support variable parts. The don't allow inheritance is important, because otherwise you'll have a certain overhead like virtual method resolution. I see. But this does not force that a synonyme for record could be a certain type of class, so that class in a straight forward and thus more future-compatible way can be used for any combination of fields of multiple types. (of course keeping the record syntax for compatibility) AFAIK even old style Turbo-Pascal Objects are still in place That could be a certain type of class as well. Yes, objects still exist as well and I still don't really understand why Borland didn't revive them instead of adding methods to records... I suppose they already marked Object as obsolete and did not want to admit the bad decision. (Of course more sensible would have been to extend the count of class specifier keywords.) Nevertheless objects are between records and classes: they can also be located on the stack (and be initialized as a constant) like records, yet they support (if you need it) inheritance and virtual methods. They can't implement interfaces though and there is no base object type (similar to TObject). Also they don't support RTTI (though I might change this with the extended RTTI). All three types, records, objects and classes have their purposes and uses and one can select the one that is most fitting in a given situation. Yep. All in fact are sensible but the multiple syntax is rather queer (disregarding the history that led to it). -Michael -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] global operator overloading
Am 26.02.2013 08:59 schrieb xrfang xrf...@gmail.com: No, it's not a dilemma, but rather a requirement. Before generics specialization, all required operations for given type must be known. This is because the symbol table when the generics is parsed must be reconstructed when it gets specialized. Think about declaring usual classes with the generic parameter replaced with actual type. If at that time, the operation is not yet defined, the code won't compile anyway. It is a pity. I think if fpc supports class operators, maybe this problem could be solved by using class helpers (my purpose is that users of ttreap class does not have to modify treap.pas) ? Is that possible in future FPC? Helpers have the same problem. For now there is only one solution (as I already wrote): require that the type with which you specialize is a record. Then a class operator in that record can be defined. For the future I already have the following longterm plans: - add class operator support to class and object - allow to specify additional units after specialize that will be used when specializing (they will be added first, so that the original code is not unnecessarily modified) Regards, Sven -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] global operator overloading
Hi Sven, Could you please give a simple example that shows what you said: require that the type with which you specialize is a record. Then a class operator in that record can be defined. Thanks 2013/2/26 Sven Barth pascaldra...@googlemail.com Am 26.02.2013 08:59 schrieb xrfang xrf...@gmail.com: No, it's not a dilemma, but rather a requirement. Before generics specialization, all required operations for given type must be known. This is because the symbol table when the generics is parsed must be reconstructed when it gets specialized. Think about declaring usual classes with the generic parameter replaced with actual type. If at that time, the operation is not yet defined, the code won't compile anyway. It is a pity. I think if fpc supports class operators, maybe this problem could be solved by using class helpers (my purpose is that users of ttreap class does not have to modify treap.pas) ? Is that possible in future FPC? Helpers have the same problem. For now there is only one solution (as I already wrote): require that the type with which you specialize is a record. Then a class operator in that record can be defined. For the future I already have the following longterm plans: - add class operator support to class and object - allow to specify additional units after specialize that will be used when specializing (they will be added first, so that the original code is not unnecessarily modified) Regards, Sven -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] global operator overloading
On 02/26/2013 09:07 AM, Sven Barth wrote: Helpers have the same problem. For now there is only one solution (as I already wrote): require that the type with which you specialize is a record. Then a class operator in that record can be defined. For the future I already have the following longterm plans: - add class operator support to class and object - allow to specify additional units after specialize that will be used when specializing (they will be added first, so that the original code is not unnecessarily modified) Here a funny question come up: Why do we (still) have records at all ? We do have classes that allow for static and/or virtual methods (of course no methods at all are possible, too. ) So why are record that now can have more than none methods. The only difference I see is that records can reside in other places than on the heap. But (if necessary) a certain type of class seems more straight forward to me (of course with record as a synonym for compatibility) . AFAIK even old style Turbo-Pascal Objects are still in place That could be a certain type of class as well. -Michael -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] global operator overloading
On 26.02.2013 09:36, Xiangrong Fang wrote: Hi Sven, Could you please give a simple example that shows what you said: require that the type with which you specialize is a record. Then a class operator in that record can be defined. Let's suppose you have the following generic declaration: === example begin === type generic TTreapT1, T2 = class // let's assume T1 requires end; === example end === If you use a record to specialize TTreap's T1 parameter then you can do it the following way: === example begin === type TMyRecord = record // note: in mode objfpc the modeswitch advancedrecords is needed class operator (aLeft, aRight: TMyRecord): Boolean; end; // implementation: class operator TMyRecord.(aLeft, aRight: TMyRecord): Boolean; begin // compare aLeft and aRight end; // somewhere else TTreapTMyRecordLongInt = specialize TTreapTMyRecord, LongInt; === example end === Now the generic will specialize without problem. If you want to specialize other types that don't support class operators then you need to wrap them inside a record, e.g.: === example begin === type TRecTStringList = record MyStringList: TStringList; class operator (aLeft, aRight: TRecTStringList): Boolean; end; === example end === You can also use visibility modifiers like private or strict private to hide the MyStringList field and make it accessible only through properties. To simplyfy usage you can also define assignment operators. E.g.: === example begin === type // maybe it will also work with a TStringList if you use TStrings instead... TRecTStringList = record private fStringList: TStringList; public class operator := (aRight: TStringList): TRecTStringList; class operator := (aRight: TRecStringList): TStringList; end; class operator TRecTStringList.:=(aRight: TStringList): TRecTStringList; begin Result.fStringList := aRight; end; class operator TRecTStringList.:=(aRight: TRecStringList): TStringList; begin Result := aRight.fStringList; end; // somewhere else: var sl: TStringList; rec: TRecStringList; begin // setup sl rec := sl; // use rec in the tree sl := rec; end; === example end === It's not the nicest solution, but currently the only thing you can do. Regards, Sven -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] global operator overloading
On 26.02.2013 10:16, Michael Schnell wrote: On 02/26/2013 09:07 AM, Sven Barth wrote: Helpers have the same problem. For now there is only one solution (as I already wrote): require that the type with which you specialize is a record. Then a class operator in that record can be defined. For the future I already have the following longterm plans: - add class operator support to class and object - allow to specify additional units after specialize that will be used when specializing (they will be added first, so that the original code is not unnecessarily modified) Here a funny question come up: Why do we (still) have records at all ? We do have classes that allow for static and/or virtual methods (of course no methods at all are possible, too. ) So why are record that now can have more than none methods. The only difference I see is that records can reside in other places than on the heap. But (if necessary) a certain type of class seems more straight forward to me (of course with record as a synonym for compatibility) . The critical difference between records and classes besides the ability of records to reside on the stack is that they don't allow inheritance and they support variable parts. The don't allow inheritance is important, because otherwise you'll have a certain overhead like virtual method resolution. AFAIK even old style Turbo-Pascal Objects are still in place That could be a certain type of class as well. Yes, objects still exist as well and I still don't really understand why Borland didn't revive them instead of adding methods to records... Nevertheless objects are between records and classes: they can also be located on the stack (and be initialized as a constant) like records, yet they support (if you need it) inheritance and virtual methods. They can't implement interfaces though and there is no base object type (similar to TObject). Also they don't support RTTI (though I might change this with the extended RTTI). All three types, records, objects and classes have their purposes and uses and one can select the one that is most fitting in a given situation. Regards, Sven -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] global operator overloading
Hi Sven, My code below: === program project1; {$mode objfpc}{$H+} {$MODESWITCH advancedrecords} uses Classes; type TMyStringList = record StringList: TStringList; class operator (s1, s2: TMyStringList): Boolean; end; class operator TMyStringList.(s1, s2: TMyStringList): Boolean; begin Result := s1.StringList.Count s2.StringList.Count; end; begin end. === generated these errors: project1.lpr(9,20) Error: It is not possible to overload this operator. Related overloadable operators (if any) are: project1.lpr(9,21) Error: It is not possible to overload this operator. Related overloadable operators (if any) are: project1.lpr(9,53) Error: Impossible operator overload project1.lpr(12,31) Error: method identifier expected project1.lpr(1,1) Fatal: Compilation aborted I am using Lazarus 1.0.6/FPC2.6.0-6 on Linux Mint 14/x86_64. Sincerely, Shannon 2013/2/26 Sven Barth pascaldra...@googlemail.com On 26.02.2013 09:36, Xiangrong Fang wrote: Hi Sven, Could you please give a simple example that shows what you said: require that the type with which you specialize is a record. Then a class operator in that record can be defined. Let's suppose you have the following generic declaration: === example begin === type generic TTreapT1, T2 = class // let's assume T1 requires end; === example end === If you use a record to specialize TTreap's T1 parameter then you can do it the following way: === example begin === type TMyRecord = record // note: in mode objfpc the modeswitch advancedrecords is needed class operator (aLeft, aRight: TMyRecord): Boolean; end; // implementation: class operator TMyRecord.(aLeft, aRight: TMyRecord): Boolean; begin // compare aLeft and aRight end; // somewhere else TTreapTMyRecordLongInt = specialize TTreapTMyRecord, LongInt; === example end === Now the generic will specialize without problem. If you want to specialize other types that don't support class operators then you need to wrap them inside a record, e.g.: === example begin === type TRecTStringList = record MyStringList: TStringList; class operator (aLeft, aRight: TRecTStringList): Boolean; end; === example end === You can also use visibility modifiers like private or strict private to hide the MyStringList field and make it accessible only through properties. To simplyfy usage you can also define assignment operators. E.g.: === example begin === type // maybe it will also work with a TStringList if you use TStrings instead... TRecTStringList = record private fStringList: TStringList; public class operator := (aRight: TStringList): TRecTStringList; class operator := (aRight: TRecStringList): TStringList; end; class operator TRecTStringList.:=(aRight: TStringList): TRecTStringList; begin Result.fStringList := aRight; end; class operator TRecTStringList.:=(aRight: TRecStringList): TStringList; begin Result := aRight.fStringList; end; // somewhere else: var sl: TStringList; rec: TRecStringList; begin // setup sl rec := sl; // use rec in the tree sl := rec; end; === example end === It's not the nicest solution, but currently the only thing you can do. Regards, Sven -- __**_ Lazarus mailing list Lazarus@lists.lazarus.**freepascal.orgLazarus@lists.lazarus.freepascal.org http://lists.lazarus.**freepascal.org/mailman/**listinfo/lazarushttp://lists.lazarus.freepascal.org/mailman/listinfo/lazarus -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] global operator overloading
On 26.02.2013 15:30, Xiangrong Fang wrote: Hi Sven, My code below: === program project1; {$mode objfpc}{$H+} {$MODESWITCH advancedrecords} uses Classes; type TMyStringList = record StringList: TStringList; class operator (s1, s2: TMyStringList): Boolean; end; class operator TMyStringList.(s1, s2: TMyStringList): Boolean; begin Result := s1.StringList.Count s2.StringList.Count; end; begin end. === generated these errors: project1.lpr(9,20) Error: It is not possible to overload this operator. Related overloadable operators (if any) are: project1.lpr(9,21) Error: It is not possible to overload this operator. Related overloadable operators (if any) are: project1.lpr(9,53) Error: Impossible operator overload project1.lpr(12,31) Error: method identifier expected project1.lpr(1,1) Fatal: Compilation aborted I am using Lazarus 1.0.6/FPC2.6.0-6 on Linux Mint 14/x86_64. Hmm... 2.6.0 seems to indeed have problems there. I did not test 2.6.2 (I don't have it installed yet), but 2.7.1 works without problems. Regards, Sven -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] global operator overloading
On 26.02.2013 15:30, Xiangrong Fang wrote: Hi Sven, My code below: === program project1; {$mode objfpc}{$H+} {$MODESWITCH advancedrecords} uses Classes; type TMyStringList = record StringList: TStringList; class operator (s1, s2: TMyStringList): Boolean; end; class operator TMyStringList.(s1, s2: TMyStringList): Boolean; begin Result := s1.StringList.Count s2.StringList.Count; end; begin end. === generated these errors: project1.lpr(9,20) Error: It is not possible to overload this operator. Related overloadable operators (if any) are: project1.lpr(9,21) Error: It is not possible to overload this operator. Related overloadable operators (if any) are: project1.lpr(9,53) Error: Impossible operator overload project1.lpr(12,31) Error: method identifier expected project1.lpr(1,1) Fatal: Compilation aborted I am using Lazarus 1.0.6/FPC2.6.0-6 on Linux Mint 14/x86_64. In addition to my previous mail: It will work in 2.6.0 if you compile in mode delphi (no $H+ and $modeswitch needed there) and you need to rename the operator from to LessThan (this is the Delphi operator name). Regards, Sven -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] global operator overloading
Then, I wish to see 2.8 released :-D thanks. 2013/2/26 Sven Barth pascaldra...@googlemail.com On 26.02.2013 15:30, Xiangrong Fang wrote: Hi Sven, My code below: ==**= program project1; {$mode objfpc}{$H+} {$MODESWITCH advancedrecords} uses Classes; type TMyStringList = record StringList: TStringList; class operator (s1, s2: TMyStringList): Boolean; end; class operator TMyStringList.(s1, s2: TMyStringList): Boolean; begin Result := s1.StringList.Count s2.StringList.Count; end; begin end. ==**= generated these errors: project1.lpr(9,20) Error: It is not possible to overload this operator. Related overloadable operators (if any) are: project1.lpr(9,21) Error: It is not possible to overload this operator. Related overloadable operators (if any) are: project1.lpr(9,53) Error: Impossible operator overload project1.lpr(12,31) Error: method identifier expected project1.lpr(1,1) Fatal: Compilation aborted I am using Lazarus 1.0.6/FPC2.6.0-6 on Linux Mint 14/x86_64. Hmm... 2.6.0 seems to indeed have problems there. I did not test 2.6.2 (I don't have it installed yet), but 2.7.1 works without problems. Regards, Sven -- __**_ Lazarus mailing list Lazarus@lists.lazarus.**freepascal.orgLazarus@lists.lazarus.freepascal.org http://lists.lazarus.**freepascal.org/mailman/**listinfo/lazarushttp://lists.lazarus.freepascal.org/mailman/listinfo/lazarus -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] global operator overloading
On 26.02.2013 15:37, Xiangrong Fang wrote: Then, I wish to see 2.8 released :-D I don't, because I still have so many things I want to implement before that :P Regards, Sven -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
[Lazarus] global operator overloading
Hi There, Days ago I posted a message about compiling error related to operator overloading. I found the reason now, but don't know how to fix that. The code is: = uses Classes, treap; type TSLCounter = specialize TTreapTStringList, Integer; operator (sl1, sl2: TStringList): Boolean; = The compiler complains about is not defined for string list. If I put the operator overloading into treap.pas, there is no problem. Is there anyway to avoid this dilemma? Because I don't want treap.pas to reversely rely on a specialized class. Thanks, Shannon-- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] global operator overloading
Is there anyway to avoid this dilemma? Because I don't want treap.pas to reversely rely on a specialized class. No, it's not a dilemma, but rather a requirement. Before generics specialization, all required operations for given type must be known. This is because the symbol table when the generics is parsed must be reconstructed when it gets specialized. Think about declaring usual classes with the generic parameter replaced with actual type. If at that time, the operation is not yet defined, the code won't compile anyway. -- View this message in context: http://free-pascal-lazarus.989080.n3.nabble.com/Lazarus-global-operator-overloading-tp4029446p4029447.html Sent from the Free Pascal - Lazarus mailing list archive at Nabble.com. -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] global operator overloading
No, it's not a dilemma, but rather a requirement. Before generics specialization, all required operations for given type must be known. This is because the symbol table when the generics is parsed must be reconstructed when it gets specialized. Think about declaring usual classes with the generic parameter replaced with actual type. If at that time, the operation is not yet defined, the code won't compile anyway. It is a pity. I think if fpc supports class operators, maybe this problem could be solved by using class helpers (my purpose is that users of ttreap class does not have to modify treap.pas) ? Is that possible in future FPC? -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus