Re: [fpc-pascal] Traits Proposal

2021-02-10 Thread Adriaan van Os via fpc-pascal

Michael Van Canneyt via fpc-pascal wrote:



On Tue, 9 Feb 2021, Ryan Joseph via fpc-pascal wrote:

We had talked about this some time ago and it's been rattling around 
in my brain so I wanted to write it down into a formal proposal where 
we can discuss it and hopefully agree upon a syntax. Everything is 
preliminary and tentative but this is a syntax which allows a 
"composition over inheritance" model, also known as "mix-ins" in some 
languages. That idea is similar to multiple inheritance except you 
have a concrete reference to the trait being implemented so you can 
resolve conflicts easily.


Here's what I have so far. Please feel free to look at it and give any 
feedback.


https://github.com/genericptr/freepascal/wiki/Traits-Proposal


In general, I am charmed by this idea.


I am, in whatever form it is implemented, also a proponent of the basic idea behind it, formulated 
on Ryan's  page as:


"Traits allow a "composition over inheritance" model which complement the existing single 
inheritance model introduced in Object Pascal. Traits are similar to multiple inheritance in 
languages such as C++ and Java, with the difference being an explicit reference to the class (or 
trait) which is being implemented."


Regards,

Adriaan van Os

___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Traits Proposal

2021-02-10 Thread Ryan Joseph via fpc-pascal


> On Feb 10, 2021, at 12:32 AM, Michael Van Canneyt via fpc-pascal 
>  wrote:
> 
> Instead of trait you might as well use simply "object", so basically we
> could simply state that instead of an interface, you can also specify an 
> object
> in the class definition:
> 
> 
> TMyClass = class (TParent,TMyTrait1,TMyTrait2)
> Public
>  property Trait1: TMyTrait1 read FTrait1 implements TMyTrait1;
>  property Trait2: TMyTrait2 read FTrait2 implements TMyTrait2;
> end;
> 

Here's the old thread 
http://free-pascal-general.1045716.n5.nabble.com/Interface-delegates-and-the-implements-property-specifier-td5734729.html#a5734741.
 I think we agreed on introducing "trait" because it makes it clear that they 
are not objects and have other limitations. Under the hood they will be objects 
but it's important that the new type exists so the compiler can limit certain 
feature, like operator overloads and constructors (see below).

What does putting them in the class hierarchy gain us? implementing duplicate 
traits is always going to be an error one way or another. I guess it's nice to 
see in the class name at least. I'll wait to hear what the compiler people 
think about this.

Again I think it was requested to implement traits using properties but in the 
simplest form all the compiler really needs to know is that 1) there is a field 
in the class and 2) the field if of type "trait". Even this would be good 
enough in theory:

type
  TMyClass = class
FTrait: TSomeTrait;
  end;

> I also don't think you should forbid constructors; In fact I think they are
> necessary if you want to support polymorphism, because I think they 
> create/set the VMT ?
> (the compiler people need to confirm this)

I think the VMT is created by adding virtual to a method in the class 
hierarchy. This is the only potentially complicated part of the feature and one 
I have lots of questions about (see my notes on the git page).

Constructors don't make sense because traits can never be instantiated by the 
programmer. There could be lifetime hooks, like AfterImplemented(parent: 
TObject) that the compiler calls automatically when a class is instantiated 
(like AfterConstruction that all Object classes can override). In fact traits 
should probably have a root class which is hidden, just like TObject.

> 
> The only obvious thing missing in your proposal is how this changes the RTTI 
> of the
> objects.

Good question. My plan currently is to make trait fields be implemented via 
automatically generated properties simply because you get lots of free 
functionally.

For methods I'm going to leverage what I'm learning from implementing "implicit 
function specialization", which is finally getting reviewed and moving forward 
after more than a year of limbo. The basic idea of overloading is the same so 
it will be easy enough for me to hook this up. The methods don't really exist 
however so they won't exist in the RTTI. Overriding methods will have bodies 
and probably work with the RTTI.

Regards,
Ryan Joseph

___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Traits Proposal

2021-02-10 Thread Michael Van Canneyt via fpc-pascal



On Wed, 10 Feb 2021, Ryan Joseph via fpc-pascal wrote:





On Feb 10, 2021, at 12:32 AM, Michael Van Canneyt via fpc-pascal 
 wrote:

Instead of trait you might as well use simply "object", so basically we
could simply state that instead of an interface, you can also specify an object
in the class definition:


TMyClass = class (TParent,TMyTrait1,TMyTrait2)
Public
 property Trait1: TMyTrait1 read FTrait1 implements TMyTrait1;
 property Trait2: TMyTrait2 read FTrait2 implements TMyTrait2;
end;



Here's the old thread 
http://free-pascal-general.1045716.n5.nabble.com/Interface-delegates-and-the-implements-property-specifier-td5734729.html#a5734741.
 I think we agreed on introducing "trait" because it makes it clear that they 
are not objects and have other limitations. Under the hood they will be objects but it's 
important that the new type exists so the compiler can limit certain feature, like 
operator overloads and constructors (see below).


I heavily object to this; We have way too much keywords as it is already. 
So unless there really is no other way I don't think we should introduce

even more.

The compiler can do the check on an object for allowed/disallowed features
as soon as it is used in a 'trait'. So there really is no advantage gained 
by using 'trait'. The check just happens in a different place: not in the
object definition, but when it is used as a trait. At that point you must 
check for duplicate names (and probably other things) anyway.


Using 'object' has the additional advantage that you can simply use existing
objects, if they fulfill any restrictions, as traits.

If you impose the use of 'trait'  you risk that you must define objects twice 
to be able to use them as a trait - once standalone, once as a trait.


In Javascript you also don't need to use special classes/objects for mixins.

I really do not see a good reason to introduce a new type and matching
keyword.

Michael.
___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Traits Proposal

2021-02-10 Thread Ryan Joseph via fpc-pascal


> On Feb 10, 2021, at 8:41 AM, Michael Van Canneyt  
> wrote:
> 
> I heavily object to this; We have way too much keywords as it is already. So 
> unless there really is no other way I don't think we should introduce
> even more.

I guess the first question is whether a "trait" is a new construct or just a 
way to import fields/methods from a  class. I like the idea of a formal new 
type so we can limit the scope of the feature instead of taking on the baggage 
of an old type like "object". I'll wait to hear from the compiler team however.

Looking back at the old thread Sven said:

"What I'm still missing however is a real use case. What you have 
presented as an example can just as easily be done with the existing 
delegates. And just to avoid having to cast the instance to the 
interface is in my opinion not enough reason for a new feature. "

so the idea wasn't rejected outright but I'm not sure if this idea even had 
their consent. I think traits/mixins are the way of the future for OOP but 
that's not certain for FPC yet. For example C# is a major language which is 
still single-inheritance only.

btw, here are some links I've gathered on how other languages support this 
concept:

• PHP (trait): https://www.php.net/manual/en/language.oop5.traits.php
• Python (mixin): https://devtut.github.io/python/mixins.html#mixin
• Swift (default protocol):
• https://nshipster.com/swift-default-protocol-implementations/
• http://machinethink.net/blog/mixins-and-traits-in-swift-2.0/

Regards,
Ryan Joseph

___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Traits Proposal

2021-02-10 Thread Michael Van Canneyt via fpc-pascal



On Wed, 10 Feb 2021, Ryan Joseph via fpc-pascal wrote:





On Feb 10, 2021, at 8:41 AM, Michael Van Canneyt  wrote:

I heavily object to this; We have way too much keywords as it is already. So 
unless there really is no other way I don't think we should introduce
even more.


I guess the first question is whether a "trait" is a new construct or just
a way to import fields/methods from a  class.  I like the idea of a formal
new type so we can limit the scope of the feature instead of taking on the
baggage of an old type like "object".  I'll wait to hear from the compiler
team however.


I don't see what baggage there is ?

You said it yourself: internally it will just be an object. Just make it 
formally so.

I also think the argument of reusing existing objects deserves consideration.

Michael.
___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Traits Proposal

2021-02-10 Thread Ryan Joseph via fpc-pascal


> On Feb 10, 2021, at 9:06 AM, Michael Van Canneyt  
> wrote:
> 
> You said it yourself: internally it will just be an object. Just make it 
> formally so.
> 
> I also think the argument of reusing existing objects deserves consideration.

Is it strange that there are extra things in the object which aren't related to 
the trait? You could declare destructors/constructors and maybe function 
modifiers that don't make sense in modern code. I don't have a strong argument 
I guess except it feels clean to start with a fresh slate. I'm also assuming 
that during development we'll find problems with how to handle feature X of 
objects which are conflicting somehow and it would be easier to have a new type 
to resolve this. I'll wait to hear from others.

Still, the biggest hurdle is getting any acceptance from the compiler team. I 
really don't like the interface delegation pattern (from Delphi?) because it 
doesn't help with namespaces but as Sven suggested this should be good enough 
for us. Traits are easy to understand and implement but the interface 
delegation requires tons of boiler plate and you still need to subscript into 
classes instead of getting a nice unified namespace.

Regards,
Ryan Joseph

___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Traits Proposal

2021-02-10 Thread Martin Frb via fpc-pascal

On 10/02/2021 16:59, Ryan Joseph via fpc-pascal wrote:

• PHP (trait): https://www.php.net/manual/en/language.oop5.traits.php



The example exposes another aspect:


|trait SayWorld {
public function sayHello() {
parent::sayHello();|


|In this case the trait has access to the object/class into which it is 
embedded. (otherwise it could not call the inherited method of the outer 
class).


Is that wanted?
(methods and fields?)

If that is wanted
- If it will be using the existing "object" (or advanced record), then 
such code is not possible.

- One might have to think about how to declare what a trait can access?
   Just allow anything in the code, and attempt to resolve when the 
trait is embedded? IMHO maybe not?


|
___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Traits Proposal

2021-02-10 Thread Ryan Joseph via fpc-pascal


> On Feb 10, 2021, at 10:17 AM, Martin Frb via fpc-pascal 
>  wrote:
> 
> The example exposes another aspect:
> 
>> trait SayWorld {
>> public function sayHello() {
>> parent::sayHello();
> 
> In this case the trait has access to the object/class into which it is 
> embedded. (otherwise it could not call the inherited method of the outer 
> class).
> 
> Is that wanted?
> (methods and fields?)
> 
> If that is wanted
> - If it will be using the existing "object" (or advanced record), then such 
> code is not possible.
> - One might have to think about how to declare what a trait can access? 
>Just allow anything in the code, and attempt to resolve when the trait is 
> embedded? IMHO maybe not?

Here's an example of how this could work. "parent" could in theory be a hidden 
field which the compiler sets for you when the class implementing the trait is 
instantiated. 

If there was no virtual/override then there would be no VMT and normal casting 
would work to call the base class method.

This is the area I'm not sure about yet, i.e. VMT table and overriding. There 
are some examples on the wiki also.



type
 TSomeTrait = trait
   public
 parent: TObject;
 procedure DoThis;
 end; 

 procedure TSomeTrait .DoThis;
 begin
// ??? here is our issue. Is this good enough to call the TBaseClass.DoThis?
TBaseClass(parent).DoThis;
 end;

 TBaseClass = class
procedure DoThis; virtual;
 end;

 TMyClass = class(TBaseClass)
   private
 _trait: TSomeTrait;
   public
 property someTrait: TSomeTrait implements _trait;
 // we need override because TBaseClass.DoThis is virtual.
 // The compiler can generate the body for us if we don't implement it.
 procedure DoThis; override;
 procedure AfterConstruction; override;
 end;

procedure TMyClass .AfterConstruction;
begin
  someTrait.parent := self;
end;

var
 c: TMyClass;
begin
 c := TMyClass.Create;
 c.DoThis;
end;

Regards,
Ryan Joseph

___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Traits Proposal

2021-02-10 Thread Ryan Joseph via fpc-pascal


> On Feb 10, 2021, at 11:09 AM, Ryan Joseph  wrote:
> 
> type
> TSomeTrait = trait
>   public
> parent: TObject;
> procedure DoThis;
> end; 
> 
> procedure TSomeTrait .DoThis;
> begin
>// ??? here is our issue. Is this good enough to call the 
> TBaseClass.DoThis?
>TBaseClass(parent).DoThis;
> end;

Thinking about this more I don't think there's even a reason for it since 
Object Pascal doesn't let you do stuff like this anyways. If you want to call 
the super class you need to use "inherited" from within the class body.  The 
example I posted only works if there is no virtual/override involved.

Regards,
Ryan Joseph

___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Traits Proposal

2021-02-10 Thread Ryan Joseph via fpc-pascal


> On Feb 10, 2021, at 12:17 PM, Ryan Joseph  wrote:
> 
> Thinking about this more I don't think there's even a reason for it since 
> Object Pascal doesn't let you do stuff like this anyways. If you want to call 
> the super class you need to use "inherited" from within the class body.  The 
> example I posted only works if there is no virtual/override involved.

Also, PHP doesn't have function overloading so they need to add all these 
complicated conflict resolution syntaxes into their implementation. For Pascal 
we don't have this problem and we can simply rely on the existing rules. The 
only exception is when you override a method that is implemented as a trait 
(see the "Overrides" section in the wiki). We may not even want to allow this 
because it's an edge case that could be resolved by explicit references. Traits 
can be VERY simple if we keep it that way.

Regards,
Ryan Joseph

___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Traits Proposal

2021-02-10 Thread Martin Frb via fpc-pascal

On 10/02/2021 20:17, Ryan Joseph via fpc-pascal wrote:



On Feb 10, 2021, at 11:09 AM, Ryan Joseph  wrote:

type
TSomeTrait = trait
   public
 parent: TObject;
 procedure DoThis;
end;

procedure TSomeTrait .DoThis;
begin
// ??? here is our issue. Is this good enough to call the TBaseClass.DoThis?
TBaseClass(parent).DoThis;
end;

Thinking about this more I don't think there's even a reason for it since Object Pascal 
doesn't let you do stuff like this anyways. If you want to call the super class you need 
to use "inherited" from within the class body.  The example I posted only works 
if there is no virtual/override involved.



Its not about the keyword to be used.
Its not even about the inheritance.

In the example from https://www.php.net/manual/en/language.oop5.traits.php
The trait accesses a method defined in the class to which the trait is 
applied. (It happens to be from the base class, but that does not matter)


In Pascal that would look like

type
  TSomeTrait = trait
  public
    procedure DoTraitFoo;
  end;

  TSomeClass = class(TObject)
  private
    trait: TSomeTrait; // whatever syntax is used so that the trait is 
added

  public
    SomeVal: Integer;
    procedure DoSome;
    procedure Dispatch(var message); override;
  end;

procedure TSomeTrait.DoTraitFoo;
begin
  inherited Dispatch(nil); // from TObject
  DispatchStr('');  // from TObject
  DoSome;  // from SomeClass
  SomeVal := 1;  // if we can access methods, then why not data
end;

In the example
|  parent::sayHello();|
"parent" does not refer to the class containing the trait. "parent" = 
"inherited"


The php example tait's sayHello hides the inherited sayHello => so 
parent is needed.


So in the example this/self of the embedded trait is the entire object 
into which it is embedded.


That means also: the trait and the class must be conflictfree even for  
private variables. (except where maybe cross unit scoping hides them???)


-
Leaving scoping/conflicts aside.

In Pascal TSomeTrait as it is given above can not compile, as it does 
not know what DoSome,SomeVal,Dispatch are. Not until it is embedded.

Well it could compile as a generic...

So, if a trait should have such access, then how to make sure the trait 
can compile?

Maybe:

  TSomeTrait = trait
  imports
// Those must be implement/provided by classes to which the trait is added.
    procedure DoSome;
    SomeVal : integer;
  public
    procedure DoTraitFoo;
  end;

Or (less flexible)
  TSomeTrait = trait
  extends(TSomeClass)  // can extend anything that is inherited from 
TSomeClass (i.e can access anything that a TSomeClass has)

  public
    procedure DoTraitFoo;
  end;
___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Traits Proposal

2021-02-10 Thread Ryan Joseph via fpc-pascal


> On Feb 10, 2021, at 12:40 PM, Martin Frb via fpc-pascal 
>  wrote:
> 
> type
>   TSomeTrait = trait 
>   public 
> procedure DoTraitFoo; 
>   end; 
> 
>   TSomeClass = class(TObject)
>   private
> trait: TSomeTrait; // whatever syntax is used so that the trait is added
>   public
> SomeVal: Integer;
> procedure DoSome;
> procedure Dispatch(var message); override;
>   end;

if it's the simple then just set a reference to TSomeClass inside of 
TSomeTrait. If the trait doesn't know anything about the implementor then you 
indeed need to use a dispatch table or something. Can't this be solved with 
existing features?

btw, I don't think we should model this based on PHP, I just gave that as an 
example. The Swift model is much more simple and does 99% of what you want. I 
think that's what we should do for Pascal also.

Regards,
Ryan Joseph

___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Traits Proposal

2021-02-10 Thread Martin Frb via fpc-pascal

On 10/02/2021 21:17, Ryan Joseph via fpc-pascal wrote:



On Feb 10, 2021, at 12:40 PM, Martin Frb via fpc-pascal 
 wrote:

type
   TSomeTrait = trait
   public
 procedure DoTraitFoo;
   end;

   TSomeClass = class(TObject)
   private
 trait: TSomeTrait; // whatever syntax is used so that the trait is added
   public
 SomeVal: Integer;
 procedure DoSome;
 procedure Dispatch(var message); override;
   end;

if it's the simple then just set a reference to TSomeClass inside of 
TSomeTrait. If the trait doesn't know anything about the implementor then you 
indeed need to use a dispatch table or something. Can't this be solved with 
existing features?

btw, I don't think we should model this based on PHP, I just gave that as an 
example. The Swift model is much more simple and does 99% of what you want. I 
think that's what we should do for Pascal also.

I don't have a pro/contra agenda on whether that feature should be part 
of the fpc trait or not.

I just saw it, and thought I raise it.

But also, if any option should be reserved for the future, then it 
matters. Because re-using "sometrait = object end" makes it less likely 
that an "implements" clause will be added (because "object" does already 
have a fully defined syntax).

So I felled it might be worth being noted.

--
Another option would be

  TSomeTrait = trait (basetrait) for (someclass_as_minimum_base_class)

for (someclass) is of course  optional (or rather default to TObject).
So sometrait then can access
   self.any_trait_identifier
   self.someclass_ident

This is a bit limiting at first, but bring in genericts
  generic TSomeTrait = trait (basetrait) for ()
Since it is a generic the compiler will not complain about unknown 
identifiers.


It can automatically specialise, when applying a trait.

Then again the "implements" clause from above could internally create a 
generic too.


--
Btw, next question that just came up

Will traits only apply to classes?

or could a record / advanced record / old object also receive traits ?


And one more thing that may at least be considered for design in case of 
future use.


Consider a Trait
TEmployeList = trait
  function  FindByUnallocateWorkTime: TEmploye;
end;

TCompany = class
end;

Now the company could have Engineers and Designers. It needs to lists
But the trait can obviously only be added once.
Yet no-one wants to copy and paste the trait to create a 2nd verson

Maybe Something like
TDesignerList = trait(TEmployeList)
  function  FindDesigerByUnallocateWorkTime: TEmploye; aliases 
FindByUnallocateWorkTime;

end;

--
Again, none of those are needed. But if they are found interesting
___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Value:x:y syntax

2021-02-10 Thread Ralf Quint via fpc-pascal

On 2/9/2021 7:26 AM, Luis Henrique via fpc-pascal wrote:



I guess one can call it optional formatting specifiers.  See documentation: 
https://www.freepascal.org/docs-html/rtl/system/str.html

I think I was lazy and didn't look in the right place, thanks Michael and 
Christo.


This is standard Pascal real number formatting since at least the mid 
'70s...


Ralf



--
This email has been checked for viruses by Avast antivirus software.
https://www.avast.com/antivirus

___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Traits Proposal

2021-02-10 Thread Ryan Joseph via fpc-pascal


> On Feb 10, 2021, at 1:51 PM, Martin Frb via fpc-pascal 
>  wrote:
> 
> I don't have a pro/contra agenda on whether that feature should be part of 
> the fpc trait or not.
> I just saw it, and thought I raise it.
> 

These issues you are raising are more related to general type 
safety/compatibility and probably beyond the scope of what traits should do. It 
also introduces lots of new concepts and syntax which make this exponentially 
more unlikely to get approved.

The only purpose of the trait is import fields/methods into a namespace of a 
struct, like multiple inheritance but with references. We should keep it as 
simple as possible imo.

> --
> Btw, next question that just came up
> 
> Will traits only apply to classes?
> 
> or could a record / advanced record / old object also receive traits ?
> 

I don't see why not but nothing is settled yet.

Regards,
Ryan Joseph

___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Traits Proposal

2021-02-10 Thread Ryan Joseph via fpc-pascal


> On Feb 10, 2021, at 2:42 PM, Ryan Joseph  wrote:
> 
>  We should keep it as simple as possible imo.

It's not as elegant as other ideas we may think of but I think it's good enough 
to let users write boilerplate methods to resolve naming conflicts. We don't 
need to introduce new syntax or concepts. This is the power of traits vs 
multiple inheritance. We get the shared namespace like normal OOP inheritance 
but have full control over any conflicts that arise by mixing in traits.



type
  TTraitA = trait
procedure DoThis;
  end;
  TTraitB = trait
procedure DoThis;
  end;
  
type
  TMyClass = class
private
  property traitA: TTraitA implements _traitA;
  property traitB: TTraitB implements _traitB;
public
  // DoThis now hides traitB.DoThis like it would in normal Object Pascal
  procedure DoThis;
  end;

procedure TMyClass.DoThis;
begin
  // resolve the conflict by directly referencing the trait
  traitA.DoThis;
end;

Regards,
Ryan Joseph

___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Traits Proposal

2021-02-10 Thread Ryan Joseph via fpc-pascal


> On Feb 10, 2021, at 10:17 AM, Martin Frb via fpc-pascal 
>  wrote:
> 
> - One might have to think about how to declare what a trait can access? 
>Just allow anything in the code, and attempt to resolve when the trait is 
> embedded? IMHO maybe not?

Sorry Martin you said a lot and I missed this. :) The plan is to only export 
fields/methods in the public section.

Regards,
Ryan Joseph

___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Traits Proposal

2021-02-10 Thread Martin Frb via fpc-pascal


On 11/02/2021 03:07, Ryan Joseph via fpc-pascal wrote:

We get the shared namespace
So basically, we get the compiler to automatically create forwarder 
methods for us (or at least that behaviour). And that is all there is. 
right?


In that case IIRC, it was said traits are not allowed constructors. Why?
Now a constructor would and should not have a forwarding method, but 
that the compiler can skip.

Yet, in my code, in the constructor of the TMyClass, I could add
  _traitA.Create
even
  _traitA := TTraitA.Create; // if the trait was not an object, but 
another class.


The compiler can with no doubt create the forwarder methods. And if I 
understand right, then that is all the compiler should do?

(Not that I advertise a trait should be a class / IMHO better not)



procedure TMyClass.DoThis;
begin
   // resolve the conflict by directly referencing the trait
   traitA.DoThis;
end;


This we already can do. Write our own forwarder method.
I understand it is for conflict resolution only. But see my example => 
as soon as you need to repeat a trait with just a change in name, you 
always need conflict resolution.

IMHO, there are many traits that a class could need more than once.

Also that only works, if a trait is included as a field.
There was at least one message in this mail-thread that suggested
  TMyClass = class(TObject, TTraitA);

The solution is on 
https://en.wikipedia.org/wiki/Trait_(computer_programming)
/alias/: an operation that creates a new trait by adding a new name 
for an existing method
Doing that for all methods, means having 2 identical traits, but with 
different names. => no conflict.




___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Traits Proposal

2021-02-10 Thread Ryan Joseph via fpc-pascal


> On Feb 10, 2021, at 7:47 PM, Martin Frb via fpc-pascal 
>  wrote:
> 
> In that case IIRC, it was said traits are not allowed constructors. Why?

Traits are meant to be a way to import fields/methods and is based off of 
"object" (so it's on the stack). This is also important for using properties to 
alias the imported fields. It's the same with subclassing, you don't need to 
manually allocate the super class because it's all one structure with a shared 
memory space. The idea is to make a viable alternative to inheritance in the 
simplest way possible.

> 
>> procedure TMyClass.DoThis;
>> begin
>>   // resolve the conflict by directly referencing the trait
>>   traitA.DoThis;
>> end;
>> 
>> 
> This we already can do. Write our own forwarder method.
> I understand it is for conflict resolution only. But see my example => as 
> soon as you need to repeat a trait with just a change in name, you always 
> need conflict resolution.
> IMHO, there are many traits that a class could need more than once.

I know it's not the most elegant but we need to keep this simple if there's 
going to be any chance of it even being considered. I will let the compiler 
team defer to this.

Regards,
Ryan Joseph

___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Traits Proposal

2021-02-10 Thread Ryan Joseph via fpc-pascal


> On Feb 10, 2021, at 7:47 PM, Martin Frb via fpc-pascal 
>  wrote:
> 
> I understand it is for conflict resolution only. But see my example => as 
> soon as you need to repeat a trait with just a change in name, you always 
> need conflict resolution.

Please post the code snippet again. I'm not sure I understand what you're 
saying. The most important thing here is that we don't allow the programmer to 
write ambiguous code. If all else fails the code must fail to compiler, if 
there's any chance of any conflict whatsoever. The first reason this idea gets 
shot down is because people think of crazy "with" statement bugs and we need to 
avoid that at all costs.

Regards,
Ryan Joseph

___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Traits Proposal

2021-02-10 Thread Martin Frb via fpc-pascal

On 11/02/2021 04:20, Ryan Joseph via fpc-pascal wrote:



On Feb 10, 2021, at 7:47 PM, Martin Frb via fpc-pascal 
 wrote:

I understand it is for conflict resolution only. But see my example => as soon 
as you need to repeat a trait with just a change in name, you always need conflict 
resolution.

Please post the code snippet again. I'm not sure I understand what you're 
saying.


TEmployeList = trait
  function  FindByUnallocateWorkTime: TEmploye;
  // other functions/members
end;

TCompany = class
end;

Now the company could have Engineers and Designers. It needs to lists
But the trait can obviously only be added once.
Yet no-one wants to copy and paste the trait to create a 2nd verson

Maybe Something like  (aliasing / no need to copy implementation)
TDesignerList = trait(TEmployeList)
  function  FindDesigerByUnallocateWorkTime: TEmploye; aliases 
FindByUnallocateWorkTime;  // no body /just a name replacement

  // and the others
end;

===>
TCompany = class
  _TraitDesigner: TDesignerList ;
  _TraitEngeneers: TEmployeList;
end;


This is clearly something that can be done later. **IF** the design is 
chosen to allow for it.



___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Traits Proposal

2021-02-10 Thread Ryan Joseph via fpc-pascal


> On Feb 10, 2021, at 9:05 PM, Martin Frb via fpc-pascal 
>  wrote:
> 
> Maybe Something like  (aliasing / no need to copy implementation)
> TDesignerList = trait(TEmployeList)
>   function  FindDesigerByUnallocateWorkTime: TEmploye; aliases 
> FindByUnallocateWorkTime;  // no body /just a name replacement
>   // and the others
> end;

I see. I used "override from" in the wiki. From my experience I don't think the 
compiler team will allow this since it adds news syntax and complexity so I 
suggest we focus on manual boilerplate functions for now. I will of course 
defer to them on these matters.

Regards,
Ryan Joseph

___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Traits Proposal

2021-02-10 Thread Martin Frb via fpc-pascal

On 11/02/2021 04:13, Ryan Joseph via fpc-pascal wrote:



On Feb 10, 2021, at 7:47 PM, Martin Frb via fpc-pascal 
 wrote:

In that case IIRC, it was said traits are not allowed constructors. Why?

Traits are meant to be a way to import fields/methods and is based off of 
"object" (so it's on the stack). This is also important for using properties to 
alias the imported fields. It's the same with subclassing, you don't need to manually 
allocate the super class because it's all one structure with a shared memory space. The 
idea is to make a viable alternative to inheritance in the simplest way possible.

"don't need to manually allocate"
I know, I am using old "object" for that already. So that is not new 
when traits come.


Hence I concluded, the "trait" feature is exactly and only an automated 
generation of forwarder-methods (well exactly they are no longer 
forwarders, but imported / to the user that writes a call to them that 
is the same in the end)


But if the above conclusion is correct (no more, no less that replacing 
the need for forwarders ), then it is reasonable to want the same 
concept for other types... I do not actually advocate it. I simple point 
out what would logically follow (rather than what may or may not be good)



___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal