Re: [PHP-DEV] Grafts, Traits, horizontal reuse

2009-04-19 Thread Larry Garfield
On Saturday 18 April 2009 12:57:19 pm Stefan Marr wrote:
 Hi Stan,

  I see this in a much simpler fashion. Treat traits as a preprocessor
  step semantically.
 
  Internally, trait methods on multiple classes may point to the same
  method to save resources, but in my opinion there's no need to
  complicate matter by introducing new resolution rules, scopes, and
  so on.
  The way I see it:
 
  1) Property/Method name conflicts on trait/class, within the class
  including the trait raises Fatal Error.

 Well, with methods this is ok, but properties are not Java fields
 which are known at compile time, so it is not that easy. Even when
 they are known beforehand things are more complicated.

 State is usually even less composable than behavior/methods.

  3) There's a single space for a class property and its trait
  properties, so access works as if it was all class properties.

 trait Counter {
var $value;
public function inc() { $this-value++; }
...
 }

 trait Color {
var $hue;
var $saturation;
var $value;
public function getRGB() { /* ... */}
...
 }

 class MyClass {
use Counter, Color;
 }

 Ok, you could argue that you than will have to refactor your property
 names in your state. But then you will break other traits. Even worth,
 this trait is defined in a widely used framework and your breaking
 other peoples code just by changing implementation details which
 should not even be visible to your users.

 I do not think that this simple model is practicable. Unfortunately,
 it is implied by the current state-less proposal, if we do not forbid
 any access to properties inside of trait methods (which sounds like a
 stupid idea to me). :(

 Regards
 Stefan

  Feedback?

Earlier in the thread, someone suggested making properties entirely restricted 
to their trait, not any using class.  If you want access to a trait's 
property, use an accessor and be done with it.  That way it doesn't matter if 
different traits use the same property names since they'll always be resolved 
relative to the method that's using them.  Is there an implementation reason 
why that would not be a feasible solution?  From a developer experience 
perspective it seems like a reasonable approach.

Also, at the risk of scope creep I will ask if any sort of runtime knowledge 
is being considered?  That is, would there be a way to at runtime get a list 
of all traits that a given class is using, or access them separately?  Would 
that be a possible way around the question of duplicate method names?  (Vis, 
reimplement the conflicting method and then specify which of the trait methods 
you want to use by calling it, or possibly calling both of them.  That would 
allow for potentially interesting use cases, and force the resolution logic 
onto the implementer rather than trying to come up with the perfect resolution 
rules for all case.  

Eg:

trait Foo1 {
  public function foo() {}
}

trait Foo2 {
  public function foo() {}
}

class Bar {
  use Foo1, Foo2;

  public function foo() { // Without this, we get a parse error
return $this-Foo1-foo();
// or
return $this-Foo2-foo();
// or
foreach ($this-traits as $trait) {
  $return[] = $trait-foo();
}
return implode(',', $return);
// or whatever makes sense for your use case.
  }
}

-- 
Larry Garfield
la...@garfieldtech.com

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] Grafts, Traits, horizontal reuse

2009-04-19 Thread Stefan Marr

Hi Larry,


Also, at the risk of scope creep I will ask if any sort of runtime  
knowledge
is being considered?  That is, would there be a way to at runtime  
get a list

of all traits that a given class is using, or access them separately?


well, the reflection API will be extended to be able to reflect about  
traits, too.

But beside this, there is no notion of traits at runtime.



 Would
that be a possible way around the question of duplicate method  
names?  (Vis,
reimplement the conflicting method and then specify which of the  
trait methods
you want to use by calling it, or possibly calling both of them.   
That would
allow for potentially interesting use cases, and force the  
resolution logic
onto the implementer rather than trying to come up with the perfect  
resolution

rules for all case.


That is already possible by means of aliasing as described in the RFC  
[1].


You can provide different aliases for the conflicting methods and then  
decide how to proceed in the method implemented in the composing class  
by calling the aliases.


Best regards
Stefan



[1] http://wiki.php.net/rfc/horizontalreuse





--
Larry Garfield
la...@garfieldtech.com

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



--
Stefan Marr
Programming Technology Lab
Vrije Universiteit Brussel
Pleinlaan 2 / B-1050 Brussels / Belgium
http://prog.vub.ac.be/~smarr


--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] Grafts, Traits, horizontal reuse

2009-04-18 Thread Stan Vassilev | FM
The question here is how to handle property accesses, in particular 
accesses to unspecified properties.
I actually would expect to have a lookup mechanism which first looks  in 
the trait, and if the property is not found there, its going to the 
object. I expect this behavior, because it is similar to what we have 
with inheritance and properties defined by a superclass.


If a property is not jet defined, I would expect it to be created in  the 
most inner scope, like local variables.
On the other hand, I also would expect, as in inheritance, properties  to 
be found defined by super classes, or the class which defines the 
composition.


But this only my intuitive solution, so this could of course be  specified 
different.


Best regards
Stefan


Hi,

I see this in a much simpler fashion. Treat traits as a preprocessor step 
semantically.


Internally, trait methods on multiple classes may point to the same method 
to save resources, but in my opinion there's no need to complicate matter by 
introducing new resolution rules, scopes, and so on.

The way I see it:

1) Property/Method name conflicts on trait/class, within the class including 
the trait raises Fatal Error.
2) Extending classes can override the property/method, unless it's a final 
method, just like as if they override normal parent class property/method.
3) There's a single space for a class property and its trait properties, so 
access works as if it was all class properties.


Feedback?

Regards,
Stan Vassilev 



--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] Grafts, Traits, horizontal reuse

2009-04-18 Thread Stefan Marr

Hi Stan,

I see this in a much simpler fashion. Treat traits as a preprocessor  
step semantically.


Internally, trait methods on multiple classes may point to the same  
method to save resources, but in my opinion there's no need to  
complicate matter by introducing new resolution rules, scopes, and  
so on.

The way I see it:

1) Property/Method name conflicts on trait/class, within the class  
including the trait raises Fatal Error.
Well, with methods this is ok, but properties are not Java fields  
which are known at compile time, so it is not that easy. Even when  
they are known beforehand things are more complicated.


State is usually even less composable than behavior/methods.

3) There's a single space for a class property and its trait  
properties, so access works as if it was all class properties.


trait Counter {
  var $value;
  public function inc() { $this-value++; }
  ...
}

trait Color {
  var $hue;
  var $saturation;
  var $value;
  public function getRGB() { /* ... */}
  ...
}

class MyClass {
  use Counter, Color;
}

Ok, you could argue that you than will have to refactor your property  
names in your state. But then you will break other traits. Even worth,  
this trait is defined in a widely used framework and your breaking  
other peoples code just by changing implementation details which  
should not even be visible to your users.


I do not think that this simple model is practicable. Unfortunately,  
it is implied by the current state-less proposal, if we do not forbid  
any access to properties inside of trait methods (which sounds like a  
stupid idea to me). :(


Regards
Stefan




Feedback?

Regards,
Stan Vassilev

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



--
Stefan Marr
Programming Technology Lab
Vrije Universiteit Brussel
Pleinlaan 2 / B-1050 Brussels / Belgium
http://prog.vub.ac.be/~smarr


--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] Grafts, Traits, horizontal reuse

2009-04-18 Thread Stan Vassilev | FM

trait Counter {
  var $value;
  public function inc() { $this-value++; }
  ...
}

trait Color {
  var $hue;
  var $saturation;
  var $value;
  public function getRGB() { /* ... */}
  ...
}

class MyClass {
  use Counter, Color;
}

Ok, you could argue that you than will have to refactor your property 
names in your state. But then you will break other traits. Even worth, 
this trait is defined in a widely used framework and your breaking  other 
peoples code just by changing implementation details which  should not 
even be visible to your users.


I do not think that this simple model is practicable. Unfortunately,  it 
is implied by the current state-less proposal, if we do not forbid  any 
access to properties inside of trait methods (which sounds like a  stupid 
idea to me). :(


Regards
Stefan


Hi,

Since the expectancy of a trait is it'll be used in many other classes 
horizontally, I wouldn't think people will start taking generic names in 
traits as they do in normal classes.

I'd personally expect this naming convention more likely:

trait Counter { protected $counterValue; }
trait Observable { protected $observableListeners; }

And so on. The benefit is it's easy to implement, understand, and use.

However if this is not acceptable to many, and we could live with the 
complication of it, the best idea for trait property access I suppose would 
be this:


trait Observable {
   protected $listeners;
}

class Any {
   use Observable;

   function accessTraitProperty() {
   var_dump($this-Observable-listeners);
   }
}

Hence namespacing trait state into an automatically created object of the 
same name, and we're done.


On the other said, a all traits could have an automatic property owner, 
which gives it access to the class state/properties.


Regards,
Stan Vassilev 



--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] Grafts, Traits, horizontal reuse

2009-04-17 Thread Stefan Marr

Hi Tom,


On 15 Apr 2009, at 16:13, Tom Boutell wrote:

PHP needs real horizontal reuse, no question.
Looking forward to get this discussion running once again after 5.3 is  
released :)


My first reaction to traits was positive - it's simple and simple is  
good.
However I'm very concerned about the implications of not allowing  
state.

In the real world people are going to want to do horizontal reuse that
involves state. So they will work around it.


I share you're concerns about state.

Even though, I would like to keep Traits as simple as possible.
From my perspective, it would be possible to introduce a full-grained  
language concept for traits like proposed in the literature [1]. But,  
it is quite complex.
On the other hand, this language constructs would be only used rarely,  
and in this rare situations, it would be probably beneficial to have  
them at hand. Merging attributes/properties of traits, aliasing and so  
on.


For the sake of simplicity, we might discuss a very basic solution.
It would be possible to introduce trait-local state only.
Thus, all properties defined in a trait are only available within  
methods of the same trait, no other operations are able to access  
these properties.


How ever, there are also corner cases. (Behavior might be different in  
case of name clashes for dynamically created properties within a  
composition, changing behavior depending on the order of method  
invocations on a single object)




My feeling is that traits should permit state and allow the renaming
of member variables just as they allow the renaming of methods.
Just to be clear, there is no such thing like renaming. Renaming is  
just not possible with a dynamic language like PHP. ($this-$bar =  
'baz'; $this-$foo();... )


Best regards
Stefan


[1] http://www.iam.unibe.ch/~scg/Archive/Papers/Berg07eStatefulTraits.pdf


--
Stefan Marr
Programming Technology Lab
Vrije Universiteit Brussel
Pleinlaan 2 / B-1050 Brussels / Belgium
http://prog.vub.ac.be/~smarr


--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] Grafts, Traits, horizontal reuse

2009-04-17 Thread Tom Boutell
On Fri, Apr 17, 2009 at 10:16 AM, Stefan Marr p...@stefan-marr.de wrote:
 For the sake of simplicity, we might discuss a very basic solution.
 It would be possible to introduce trait-local state only.
 Thus, all properties defined in a trait are only available within methods of 
 the same trait,
 no other operations are able to access these properties.

Yes, I think this is exactly right. Programmers who want to expose the
state can do that by writing setters and getters. A trivial
inconvenience compared to the pain of not being able to have multiple
enhancements of the same third party class from multiple sources -
something that comes up almost immediately when you start talking
about plug-ins for frameworks.

 How ever, there are also corner cases. (Behavior might be different in case
 of name clashes for dynamically created properties within a composition,
 changing behavior depending on the order of method invocations on a single
 object)

I'm not sure I grasp how these can happen in this scenario.

 Just to be clear, there is no such thing like renaming. Renaming is just not
 possible with a dynamic language like PHP. ($this-$bar = 'baz';
 $this-$foo();... )

OK, but with strictly-trait-local state this is not an issue.

A shame this can't be in 5.3 but we will get there. (:

-- 
Tom Boutell
P'unk Avenue
215 755 1330
punkave.com
window.punkave.com

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] Grafts, Traits, horizontal reuse

2009-04-17 Thread Stefan Marr

Hi Tom,

On 17 Apr 2009, at 19:20, Tom Boutell wrote:
How ever, there are also corner cases. (Behavior might be different  
in case
of name clashes for dynamically created properties within a  
composition,
changing behavior depending on the order of method invocations on a  
single

object)


I'm not sure I grasp how these can happen in this scenario.


Well, it actually depends on the strictness of this idea. And its  
particular implementation.
With the dynamic nature of PHP in mind, my first idea would be  
something like this, which is not ideal:


class Base {
  // private $a; - intentionally left out because of
  //some smart approach to use meta-programming  
powers...

  public function setA($value) {
$this-a = $value;
  }
  public function echoA() {
echo $this-a;
  }
}

trait TraitUsingA {
  // var $a; - intentionally left out because of another smart  
approach for using

  // really clever meta-programming, not shown here
  public function setTraitA($value) {
$this-a = $value;
  }
  public function echoTraitA() {
echo $this-a;
  }
}

class MyClass {
  use TraitUsingA;
}

$a = new MyClass();
$a-setTraitA('trait');
$a-setA('base');
$a-echoTraitA();  // echos 'trait'
$a-echoA();   // echos 'base'

$b = new MyClass();
$b-setA('base');
$b-setTraitA('trait');
$b-echoTraitA();  // echos 'trait'
$b-echoA();   // echos 'trait'

The question here is how to handle property accesses, in particular  
accesses to unspecified properties.
I actually would expect to have a lookup mechanism which first looks  
in the trait, and if the property is not found there, its going to the  
object. I expect this behavior, because it is similar to what we have  
with inheritance and properties defined by a superclass.


If a property is not jet defined, I would expect it to be created in  
the most inner scope, like local variables.
On the other hand, I also would expect, as in inheritance, properties  
to be found defined by super classes, or the class which defines the  
composition.


But this only my intuitive solution, so this could of course be  
specified different.


Best regards
Stefan



--
Stefan Marr
Programming Technology Lab
Vrije Universiteit Brussel
Pleinlaan 2 / B-1050 Brussels / Belgium
http://prog.vub.ac.be/~smarr


--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] Grafts, Traits, horizontal reuse

2009-04-15 Thread Tom Boutell
I've been catching up with the discussion of grafts and traits. Here
at P'unk Avenue we do a lot of Symfony development, which frequently
involves kludges to achieve horizontal reuse - ugly, clever,
imaginative, combinations of the three but the first of the three is
pretty much always present. PHP needs real horizontal reuse, no
question.

My first reaction to traits was positive - it's simple and simple is good.

However I'm very concerned about the implications of not allowing state.

In the real world people are going to want to do horizontal reuse that
involves state. So they will work around it.

It's true that if they are extending a class they have control over,
they can do it fairly elegantly...

In the parent class:

public $traitData = null;
public function __construct()
{
  $traitData = array();
}

Now, in a trait method, they can do:

public function mymethod()
{
  $this-traitData['age'] = 38;
}

The PHP 5.3 cycle breaker can presumably clean up any references made
in traitData when all noncyclical references to the object itself are
gone.

However this is not without problems. There will be collisions between
key names in traitData when mixing traits, and there will be no way to
detect those conflicts and automatically resolve them. It's presumably
less efficient than an implementation of state in the core.  And most
importantly, it only works if the parent class can be modified by the
programmer trying to extend it. One of the stated goals of horizontal
reuse is to accommodate adding multiple non-mutually-exclusive
extensions, written by you and not written by you, to parent classes
you didn't write (of course, without the written by you and not
written by you... multiple non-mutually-exclusive part, you could
just use a subclass).

So what happens when the programmer wants to write a trait to extend
classes they didn't write, and they need to save state?

Well, their first workaround attempt might be this:

$foo-bar = I'm an object!;
$hash[$foo]['age'] = 5;
echo($hash[$foo]['age']);

That is, use the object as a key in a hash.

Fortunately, PHP doesn't allow objects as keys in hashes. That's good,
because this otherwise clever technique would leave stray references
in the hash which would never get cleaned up, ever. Cycle breaking or
no cycle breaking. We're right back in why can't I manipulate a lot
of objects in a 'for' loop without hating life land.

Okay, so what's our hypothetical user's next workaround going to be?

In some cases, they're just stuck. In others, the parent class does
offer some sort of unique identifier. Common examples being Propel and
Doctrine objects, which have getId() methods. So the programmer does
this (simplest possible implementation to show the idea):

public function myTraitMethod()
{
  global $hash; // *
  $hash[$this-getId()]['age'] = 38;
}

This works. But it leaks memory forever. When the object goes away,
there is no way to break the connection to the data in $hash. Which
might not be as trivial as 'age'. More likely it'll be crammed with
objects with references to objects with... you get the idea.

To clean these references up you'd need a destructor. Except the
traits RFC makes no mention of destructors. So you'd need a parent
class destructor that explicitly invoked trait destructors. Except you
went this road in the first place because you didn't have control over
the parent class to make changes like that. Etc.

Since PHP is moving in the direction of better garbage collection (and
thank heaven for that), it's a bad idea to make a design decision that
will lead developers in the direction of breaking that garbage
collection system.

The natural thought at this point is to endorse grafts. But the grafts
proposal has more complex implementation requirements and there
doesn't seen to be an existing patch to implement it. The big
stumbling point is that in a naive implementation, $this would refer
to the graft object, not its parent. But the programmer expects to be
able to pass $this around to other code which will expect the parent
object, etc.

My feeling is that traits should permit state and allow the renaming
of member variables just as they allow the renaming of methods. If
that's an implementation problem, it might be better to transparently
move the trait member variables to a hash and interpret references to
those variable names accordingly within the trait methods. The member
variable hash becomes $this-__traitName_0, $this-__traitName_1, etc.
for each consecutive use of the same trait in the same class (if we
really need that feature).

(*) Yes, $hash shouldn't be a global, it should be a static member of
a globalDataManager class or something. Makes no difference for
purposes of this discussion.

-- 
Tom Boutell
P'unk Avenue
215 755 1330
punkave.com
window.punkave.com

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] Grafts, Traits, horizontal reuse

2008-11-26 Thread Alan Pinstein

On Nov 24, 2008, at 9:27 PM, Christopher Vogt wrote:

Interfaces are helpful in combination with type hinting, but for  
people who prefer

duck typing, it is reasonable to not explicitly define them.


It sounds like you are saying that if you prefer duck typing then  
interfaces have no use.


If this is what you mean, I disagree strongly.

Interfaces are primarily to create a set of methods that define an  
interface. Then the compiler can enforce implementation of that  
interface in any class that claims to implement the interface. This is  
the core utility of interfaces.


Alan

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] Grafts, Traits, horizontal reuse

2008-11-25 Thread Marcus Boerger
Hello Christopher,

Tuesday, November 25, 2008, 3:27:45 AM, you wrote:

 Hej Marcus,

 I like your approach. It is clear and simple. It would probably solve
 90% of the cases, where delegation is needed.

 I want to add that a manually defined method should automatically
 overwrite a delegated method of the same name.

 But I also want to bring up two reasonable situations your approach does
 not cover. Your approach does not allow to delegate only a selection of
 methods. This makes sense in order to limit the delegation to known
 functionality. To stick to your example, without selective delegation,
 new methods added to Counter would be automatically delegated to
 CounterUser. This might break things.

 A second situation not covered by your approach is renaming of delegated
 methods. This can be desirable due to name clashes or name changes for
 better understandability.

 Of course there is always the fall back to manually implementing
 delegation. And your approach alone would already be quite useful
 syntactic sugar. But additional syntactic sugar for the two situations
 described above would still be nice :).

 Another thing. I am not sure if you intended that, but I think
 delegation should not force using an Interface definition. Interfaces
 are helpful in combination with type hinting, but for people who prefer
 duck typing, it is reasonable to not explicitly define them. Let's leave
 this choice to the people :).

Your points are all well observed. And yes I limit what my approach can
do in order to Keep It Simple Safe (KISS). While still being able to
manually interfere with/overload the autogenerated code when necessary.
At the same time forcing to delegate to a defined Interface and not
allowing to rename on the fly prevents abusing the functionality and
helps maintainability. On the other hand it forces you to think before
coding as this approach comes with a lack of functionality.

Maybe in a second step we could make the defined interface optional but
with my implementation in mind that might not be the easiest thing to do.

 Best regards

 Christopher




Best regards,
 Marcus


-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] Grafts, Traits, horizontal reuse

2008-11-25 Thread Stefan Marr

Hi,

On 25 Nov 2008, at 13:39, Marcus Boerger wrote:


Your points are all well observed. And yes I limit what my approach  
can

do in order to Keep It Simple Safe (KISS). While still being able to
manually interfere with/overload the autogenerated code when  
necessary.

At the same time forcing to delegate to a defined Interface and not
allowing to rename on the fly prevents abusing the functionality and
helps maintainability. On the other hand it forces you to think before
coding as this approach comes with a lack of functionality.


Ok, but now we start to talk about two clearly different things.
On the one hand something like traits, mixins, or what ever, and  
restricted syntax sugar for delegation on the other hand.


While designing grafts, the idea was to provide a similar power like  
traits do, but introducing state and encapsulation. From my point of  
view, there is no other way to achieve this. At least I have not found  
it.
All things in between, like unbreakable traits add more complexity  
then they solve problems.


So actually, we are somewhere near the point which I intended to reach  
with my proposal.


The questions we should answer now are:
  - Does PHP need horizontal reuse?
  - Do we go for an explicit solution? (traits)
  - Do we go for some sort of syntax sugar for delegation? (grafts,  
delegate keyword)

  - Or do we go the implicit way? (mixins, phyton multiple-inheritance)

Nevertheless, I would love to get some more comments on grafts before  
answering this questions, because this could give additional insights  
in the real problems with this approach and some ideas for improvements.


Best Regards
Stefan

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] Grafts, Traits, horizontal reuse

2008-11-25 Thread Lars Strojny
Hi Christopher,

thanks for (re-)starting the discussion how to make horizontal reuse
easier in PHP.

Am Donnerstag, den 13.11.2008, 16:59 +0100 schrieb Christopher Vogt:
[...]
 I had a chat with Stefan about his Traits/Grafts RFC and he suggested we
 should rather continue a discussion here.
 I really liked to see the Grafts proposal. In traits and regular
 inheritance the implementation code of several entities is somehow mixed
 and as a result one entities code can break another entities code.

To keep things fair, there were proposals to keep traits completely
stateless and to allow abstract methods in traits, so that traits can
sort of request the implementation of a certain method. This would
keep the inheritance chain pretty stable.

 The
 great thing about Grafts is that the implementation is not mixed. Grafts
 are completely encapsulated entities with their own state. I think in
 many cases where inheritance or traits seem tempting, complete
 encapsulation is actually the cleaner solution.

I see the point of having encapsulated state, I still wonder if it would be 
better for us to have something simpler. Simpler, as in avoiding state at all. 
So if we had traits without state at all a) the concept is easy to explain 
(like interfaces define the API, classes keep state, traits encapsulate 
implementation). A nice and easy explainable hierarchy of responsibilities.

[... Details about grafts ...]

 However a problem remains. The methods of counter return $this (aka
 implement a fluent interface). One idea that came to my mind to solve
 this problem: PHP could provide a keyword fluent that replaces a methods
 return value to form a fluent interface i.e. return $this:
 
 class QueueTicketPrinter{
   use Counter as private $counter{
 public fluent current();
 public fluent reset();
   }
   public function takeNumber(){
 print 'your number is .$this-counter-current();
 $this-counter-inc();
   }
 }
 
 The keyword fluent ignores whatever value the Counter function may
 return and returns an the instance of QueueTicketPrinter instead.

That's a good example why I have the feeling they are a hack. I mean a
fluent keyword just for a single use case. Another thing, how could I
return the class name of the current class? public class current().
And so on. At the end it is an issue of late graft binding (similar to
late static binding).

 Finally, can somebody provide a sensible use case for traits, that
 cannot be solved with Grafts? I am sure there is, but I am currently
 lacking one.

I can't think of any (except from late graft binding), however not
having anything against does not mean it is a good idea :) I still
prefer traits as they are easier to explain from my point of view, the
concept is more clear and that's the spirit that fits pretty well for
PHP.

cu, Lars


signature.asc
Description: Dies ist ein digital signierter Nachrichtenteil


Re: [PHP-DEV] Grafts, Traits, horizontal reuse

2008-11-24 Thread Marcus Boerger
Hello Stefan,

Sunday, November 16, 2008, 4:36:18 PM, you wrote:

 Hi,

 Christopher Vogt schrieb:
 Hej everybody,
 
 I really liked to see the Grafts proposal.
 Well, I'm still in love with the more powerful (because they are 
 interweaveable(breakable)) Traits ;)


 The Grafts proposal, however, suffered a little from being born out of
 traits, I think. Something similar to Grafts is already possible in
 current php, but it is not very beautiful. If we start from there
 however, Grafts could become very helpful syntactic sugar. 
 Actually I think this could be a problem for the conciseness of the 
 language. Introducing syntactic sugar for special situations has to be 
 done carefully. Nevertheless, from my perspective forwarding (aka 
 delegation) is a very common concept in OOP which would be worth to be 
 supported by a special syntax.

 class QueueTicketPrinter{
   use Counter as private $counter{
 public current();
 public reset();
   }
   public function takeNumber(){
 print 'your number is .$this-counter-current();
 $this-counter-inc();
   }
 }
 I like this idea, but there are still some problems to be solved. The 
 major problem with grafts is still the initialization of objects. What 
 to do with constructors which require parameter?
 An other issue I see is the question of introducing to much additional 
 syntax. It could be reduced to something like:

 private $counter : Counter [use] {  //with or without use?
  public current();
  public reset();
 }

 But now anonymous grafts aren't possible anymore and actually, Grafts 
 had been design without an identity own their own. On the other hand, 
 this notation could introduce the possibility for advanced initialization:

 class QueueTicketPrinter{
  private $cntInitValue;
  public function __construct($cntValue) {
  $this-cntInitValue = $cntValue;
  }

  private $counter : Counter(cntInitValue) {
  public current();
  public reset();
  }

  public function takeNumber(){
  print 'your number is .$this-counter-current();
  $this-counter-inc();
  }
 }

This is hardly more than delegates. Actually the only thing more you get is
hiding stuff which is incompatible to the thing you loose at the same time.
That is your grafts do not support interface delegation. So My preference
is being able to actually do that (and mixins/traits do). Example:

Interface Counter {
  function current();
  function reset();
}

Class CounterImpl implements Counter {
  private $cnt = 0;
  function current() { return $this-cnt; }
  function reset() { $this-cnt = 0; }
}

Class CounterUser implements Counter {
  delegate Counter $counter;
  function __construct() {
$this-counter = new CounterImpl;
  }
}

The keyword delegate makes sure $counter is a member that must implement
Counter. Assigning any other value would result in an exception or other
error. To make it easier the delegate declaration wcould contain the
initialization already and turn the delegate member into a read only
member.

deletegate Counter $counter = new CounterImpl;

 Finally, can somebody provide a sensible use case for traits, that
 cannot be solved with Grafts? I am sure there is, but I am currently
 lacking one.
 Every time you just like to compose a class from different kinds of 
 behaviors Traits are superior. The use cases discussed in literature are 
 class hierarchies for collection classes and streams. For both 
 hierarchies, the interweaving of methods from different traits is a 
 helpful property to build all variations of semantics.


 Kind Regards
 Stefan

marcus




Best regards,
 Marcus


-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] Grafts, Traits, horizontal reuse

2008-11-24 Thread Christopher Vogt
Hej Marcus,

I like your approach. It is clear and simple. It would probably solve
90% of the cases, where delegation is needed.

I want to add that a manually defined method should automatically
overwrite a delegated method of the same name.

But I also want to bring up two reasonable situations your approach does
not cover. Your approach does not allow to delegate only a selection of
methods. This makes sense in order to limit the delegation to known
functionality. To stick to your example, without selective delegation,
new methods added to Counter would be automatically delegated to
CounterUser. This might break things.

A second situation not covered by your approach is renaming of delegated
methods. This can be desirable due to name clashes or name changes for
better understandability.

Of course there is always the fall back to manually implementing
delegation. And your approach alone would already be quite useful
syntactic sugar. But additional syntactic sugar for the two situations
described above would still be nice :).

Another thing. I am not sure if you intended that, but I think
delegation should not force using an Interface definition. Interfaces
are helpful in combination with type hinting, but for people who prefer
duck typing, it is reasonable to not explicitly define them. Let's leave
this choice to the people :).

Best regards

Christopher

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] Grafts, Traits, horizontal reuse

2008-11-16 Thread Stefan Marr

Hi,

Christopher Vogt schrieb:

Hej everybody,

I really liked to see the Grafts proposal.
Well, I'm still in love with the more powerful (because they are 
interweaveable(breakable)) Traits ;)




The Grafts proposal, however, suffered a little from being born out of
traits, I think. Something similar to Grafts is already possible in
current php, but it is not very beautiful. If we start from there
however, Grafts could become very helpful syntactic sugar. 
Actually I think this could be a problem for the conciseness of the 
language. Introducing syntactic sugar for special situations has to be 
done carefully. Nevertheless, from my perspective forwarding (aka 
delegation) is a very common concept in OOP which would be worth to be 
supported by a special syntax.



class QueueTicketPrinter{
  use Counter as private $counter{
public current();
public reset();
  }
  public function takeNumber(){
print 'your number is .$this-counter-current();
$this-counter-inc();
  }
}
I like this idea, but there are still some problems to be solved. The 
major problem with grafts is still the initialization of objects. What 
to do with constructors which require parameter?
An other issue I see is the question of introducing to much additional 
syntax. It could be reduced to something like:


private $counter : Counter [use] {  //with or without use?
public current();
public reset();
}

But now anonymous grafts aren't possible anymore and actually, Grafts 
had been design without an identity own their own. On the other hand, 
this notation could introduce the possibility for advanced initialization:


class QueueTicketPrinter{
private $cntInitValue;
public function __construct($cntValue) {
$this-cntInitValue = $cntValue;
}

private $counter : Counter(cntInitValue) {
public current();
public reset();
}

public function takeNumber(){
print 'your number is .$this-counter-current();
$this-counter-inc();
}
}




Finally, can somebody provide a sensible use case for traits, that
cannot be solved with Grafts? I am sure there is, but I am currently
lacking one.
Every time you just like to compose a class from different kinds of 
behaviors Traits are superior. The use cases discussed in literature are 
class hierarchies for collection classes and streams. For both 
hierarchies, the interweaving of methods from different traits is a 
helpful property to build all variations of semantics.



Kind Regards
Stefan



--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] Grafts, Traits, horizontal reuse

2008-11-16 Thread Christopher Vogt
Hej,

 I really liked to see the Grafts proposal.
 Well, I'm still in love with the more powerful (because they are
 interweaveable(breakable)) Traits ;)

I don't think there has to be a choice between Grafts and Traits. They
serve different purposes and I don't see a reason they shouldn't
co-exit. Traits implement code reuse. Code is merged. This is very
powerful but can break code. Grafts implement delegation. This is less
powerful, but can't break, which makes it preferable, whenever possible.

 Actually I think this could be a problem for the conciseness of the
 language. Introducing syntactic sugar for special situations has to be
 done carefully.

In my eyes (well-chosen) syntactic sugar contributes a lot to language
conciseness. And every language decision should be done carefully, right?

 from my perspective forwarding (aka
 delegation) is a very common concept in OOP which would be worth to be
 supported by a special syntax.

I strongly think so.

 I like this idea, but there are still some problems to be solved. The
 major problem with grafts is still the initialization of objects. What
 to do with constructors which require parameter?

Good point. My new suggestion at the end covers it.

 An other issue I see is the question of introducing to much additional
 syntax. It could be reduced to something like:
 
 private $counter : Counter [use] {  //with or without use?
 public current();
 public reset();
 }

I don't see the above having less syntax than my suggestion. as or :
is both syntax. I doubt, I would rather stick to a keyword already in
the language in similar semantics. For Comparison, my suggestion was:

   use Counter as private $counter{
 public current();
 public reset();
   }


 But now anonymous grafts aren't possible anymore and actually, Grafts
 had been design without an identity own their own.

Yes and I don't think anonymous Grafts would be a good idea. They would
make access to grafts complicated and significantly limited including
valid use cases. Being explicit instead of implicit helps here in my eyes.

 On the other hand,
 this notation could introduce the possibility for advanced initialization:
 
 private $cntInitValue;
 public function __construct($cntValue) {
 $this-cntInitValue = $cntValue;
 }
 
 private $counter : Counter(cntInitValue) {
 public current();
 public reset();
 }

I don't think that's a good idea. I admit it's very close to my
suggestion, but now it reached a point, where it does something very
familiar, namely creating an new object, using a very unfamiliar way and
also new syntax. So I make a new suggestion that puts everything much
closer to present PHP:

 class QueueTicketPrinter{
 private $counter {
 public current();
 public restart() from reset();
 };

 public function __construct($cntValue) {
 $this-counter = new Counter( $cntValue );
 }

 public function takeNumber(){
 print 'your number is .$this-current();
 $this-counter-inc();
 }
 }

And two syntax variants:

Variant 1:
 private $counter use {
 public current();
 reset() as public restart();
 };

Variant 2:
 private $counter delegate {
 public current();
 public restart() to reset();
 };


This suggestion requires a new runtime Error/Exception for cases when a
method of QueueTicketPrinter is called that is delegated to a method
that $counter does not implement.

 Every time you just like to compose a class from different kinds of
 behaviors Traits are superior. 

More powerful yes, superior no. Delegation and inheritance (counting
traits as a variant of inheritance) both allow functionality re-use but
both also resemble a trade-off between flexibility and breakability.
Inheritance is more flexible, but can easily break, especially when
inheritance structures grow. Delegation is less flexible, but can't
break (from reuse), even in large structures. So both are justified.

Best regards

Christopher

P.S. I should mention that I do not have any insight of the actual
implementation of PHP. So if I suggest something insensibly hard to
implement, just shout :).

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



[PHP-DEV] Grafts, Traits, horizontal reuse

2008-11-13 Thread Christopher Vogt
Hej everybody,

I had a chat with Stefan about his Traits/Grafts RFC and he suggested we
should rather continue a discussion here.

I really liked to see the Grafts proposal. In traits and regular
inheritance the implementation code of several entities is somehow mixed
and as a result one entities code can break another entities code. The
great thing about Grafts is that the implementation is not mixed. Grafts
are completely encapsulated entities with their own state. I think in
many cases where inheritance or traits seem tempting, complete
encapsulation is actually the cleaner solution.

The Grafts proposal, however, suffered a little from being born out of
traits, I think. Something similar to Grafts is already possible in
current php, but it is not very beautiful. If we start from there
however, Grafts could become very helpful syntactic sugar. Let's look at
current PHP first:

class Counter {
  private $cnt = 0;
  public function inc() {
$this-cnt++;
return $this;
  }
  public function reset() {
$this-cnt = -1;
$this-inc();
return $this;
  }
  public function current(){
   return $this-cnt;
return $this;
  }
}
class QueueTicketPrinter{
  private $counter;
  public __construct(){
$this-counter = new Counter();
  }
  public function takeNumber(){
print 'your number is .$this-counter-current();
$this-counter-inc();
  }
  public function current(){
$this-counter-current();
  }
  public function reset(){
$this-counter-reset();
  }
}

This is a lot of code in QueueTicketPrinter for that it mostly reuses
Counter. Grafts as syntactic sugar could make it look as short as:

class QueueTicketPrinter{
  use Counter as private $counter{
public current();
public reset();
  }
  public function takeNumber(){
print 'your number is .$this-counter-current();
$this-counter-inc();
  }
}

However a problem remains. The methods of counter return $this (aka
implement a fluent interface). One idea that came to my mind to solve
this problem: PHP could provide a keyword fluent that replaces a methods
return value to form a fluent interface i.e. return $this:

class QueueTicketPrinter{
  use Counter as private $counter{
public fluent current();
public fluent reset();
  }
  public function takeNumber(){
print 'your number is .$this-counter-current();
$this-counter-inc();
  }
}

The keyword fluent ignores whatever value the Counter function may
return and returns an the instance of QueueTicketPrinter instead.

Finally, can somebody provide a sensible use case for traits, that
cannot be solved with Grafts? I am sure there is, but I am currently
lacking one.

Cheers

Christopher

P.S. Hope that stupid post before does not make me seem too much like it ;).

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php