Re: [Lazarus] global operator overloading

2013-02-27 Thread Michael Schnell

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

2013-02-26 Thread Sven Barth
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

2013-02-26 Thread Xiangrong Fang
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

2013-02-26 Thread Michael Schnell

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

2013-02-26 Thread Sven Barth

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

2013-02-26 Thread Sven Barth

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

2013-02-26 Thread Xiangrong Fang
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

2013-02-26 Thread Sven Barth

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

2013-02-26 Thread Sven Barth

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

2013-02-26 Thread Xiangrong Fang
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

2013-02-26 Thread Sven Barth

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

2013-02-25 Thread xrfang
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

2013-02-25 Thread leledumbo
 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

2013-02-25 Thread xrfang
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