# [RFC] prototyping

- Thread: https://externals.io/message/42592
- Original archive: https://news-web.php.net/php.internals/42592
- Started by Marcus Boerger on 2009-01-12T22:32:04+00:00
- Messages: 37
- Page 1 of 2: messages 1 to 25 (25 per page, add `?page=N` to the URL)
- Next page: https://externals.io/message/42592.md?page=2
- Reply by email to internals@lists.php.net
- More for agents: search with https://externals.io/search.md?q={query} · JSON API at https://externals.io/api · documentation at https://externals.io/llms.txt

---

## #42592 — Marcus Boerger — 2009-01-12T22:32:04+00:00

URL: https://externals.io/message/42592#42592

Hello Internals,

  our new closures can easily work as prototypes and I actually thought
of simply doing it as a bug fix. But it appeared that my first attempt
was inclomplete if not to say completely wrong. It further more turned
out that not everyone is a fan of the genral idea.

Basically what I expected is that closures assigned to object properties
behave in the same way prototypes behave. That is:

1) a non static closure assigned to an instance changes the closures
this to be set to the actual object:
$closure = function() {}
// $closure->this == `NULL` 
$obj1->property = $closure;
// $obj1->property->this == $obj1;
// $closure->this == `NULL` 

2) a static closure assigned to an instance sets the closure's scope

1+2) both give access to private members

3) Assignment of a closure from one object property to another objects
property changes it $this.
$obj2->property = $obj1->property;
// $obj1->property->this == $obj1
// $obj2->property->this == $obj2

4) Cloning an object assigns the properties correct. Right now we
increase the refcount only instead of cloning as that is the default
behavior of cloning. Since a normal variable splits on changes nothing
ever notices this. For oject types that do not support cloning this is
very different though. Now we cannot simply add cloning as then we'd
further change closure behavior. And this way we would not fix the this
pointer.
$obj3 = clone $obj;
// $obj3>property->this == $obj3

5) A closure assigned to a property can be called directly rather
than just by a temporary variable:
$obj->property = function() {}
$obj->property();  // valid call

The above requires the following internal modifications:

1) Closures internally support clone, but do not set the actual handler,
thus preventing anything else from cloning them (current behavior).

2) Default object cloning does not only call add_ref per member variable
but also checks for a member being a prototype method in which case it
performs the necessary cloning of that property.

3) An additonal check in the default property get handler is reaquired
to check for a closure property (prototype) in case a function cannot be
found. Unless someone uses closures there will be no change in behavior.
If this gets done later we will change behavior.

Why did I work on this:

1) Because to me the current implementation is broken. While as closures
themselves work perfect, they simply work very unexpected when assigned
to an object.

2) The current behavior seems inconsistent as it matters where an
assignment of a closure to a proeprty is being performed. OR how a closure
is being created.

3) The current behavior can be used as an impleentation of prototype
methods in PHP. However it just does a very tiny subset that makes it
a broken implementation. So we will end up in a situation where users see
prototype methods but don't get them to work.

4) We could finally get more consistency because we would have a partial
protoype ojbect model not only for member variables but also for member
functions.

Issues that speak against this:

1) A closure bound to a property is case sensitive  unlike a member
function. We have this however anyway. As we already have functions
callable by variables whether the variable is a closure or just a
function name.

2) To close to a release. Well that's why we have beta cycles to identify
tsituations like this.

3) If closures get callable by property directly then we end up in a
situation where we can have two methods with the same name. That means it
is discussable whether we want to allow assignment of a closure to a
member variable name that already exists as a private member function.

Best regards,
 Marcus

---

## #42593 — Stanislav Malyshev — 2009-01-12T23:07:31+00:00

URL: https://externals.io/message/42592#42593 · In reply to: #42592

Hi!

> 1) a non static closure assigned to an instance changes the closures
> this to be set to the actual object:

I'm not sure why would you expect this. If you have closure that has 
some bound $var inside, and you use it in context which has another 
$var, you don't expect that $var change to new scope's $var, do you?
I always thought of closures as taking their variables and context with 
them, not changing them each time caller changes.

Also, this adds very new thing to PHP - objects that change while being 
assigned. I am not sure it is a good thing.

> 4) Cloning an object assigns the properties correct. Right now we
> increase the refcount only instead of cloning as that is the default
> behavior of cloning. Since a normal variable splits on changes nothing
> ever notices this. For oject types that do not support cloning this is
> very different though. Now we cannot simply add cloning as then we'd
> further change closure behavior. And this way we would not fix the this
> pointer.

Besides the issue above with changing $this I'm not sure what would 
proper clone do - i.e. by-val bound variables are by-val anyway, so it 
shouldn't matter if they are cloned, and by-ref ones should be connected 
anyway so again it doesn't matter. Am I missing something?
BTW, why would one clone closures anyway?

> 5) A closure assigned to a property can be called directly rather
> than just by a temporary variable:
> $obj->property = function() {}
> $obj->property();  // valid call

This will get us into trouble IMHO, as it would not behave too well with 
  __get/__set and __call. I.e. if we have $foo->nosuchproperty() - 
should we call __get or __call? So far variables implemented through 
__get behave exactly like ones implemented through definition - but I 
don't understand how to reconcile it with this.

I also don't like having special one-class check inside assignment 
operators just for this narrow function - it doesn't look like good 
generic code and I suspect for proper implementation may require 
instanceof check on each assignment - which would be really bad.

> 2) The current behavior seems inconsistent as it matters where an
> assignment of a closure to a proeprty is being performed. OR how a closure
> is being created.

Of course it matters how (or, more precisely, where) the closure was 
created - isn't it the whole point of closure?

> 3) If closures get callable by property directly then we end up in a
> situation where we can have two methods with the same name. That means it
> is discussable whether we want to allow assignment of a closure to a
> member variable name that already exists as a private member function.

This is another thing - does it mean on each assignment we'd have to 
check if member function with same name doesn't exist? That might break 
some code in interesting ways too.
-- 
Stanislav Malyshev, Zend Software Architect
stas@zend.com   http://www.zend.com/
(408)253-8829   MSN: stas@zend.com

---

## #42610 — Etienne Kneuss — 2009-01-13T19:44:57+00:00

URL: https://externals.io/message/42592#42610 · In reply to: #42593

Hello,


> Hi!
>
> > […]
>
> I'm not sure why would you expect this. If you have closure that has some
> bound $var inside, and you use it in context which has another $var, you
> don't expect that $var change to new scope's $var, do you?
> I always thought of closures as taking their variables and context with
> them, not changing them each time caller changes.
>
> Also, this adds very new thing to PHP - objects that change while being
> assigned. I am not sure it is a good thing.
>
> > […]
>
> Besides the issue above with changing $this I'm not sure what would proper
> clone do - i.e. by-val bound variables are by-val anyway, so it shouldn't
> matter if they are cloned, and by-ref ones should be connected anyway so
> again it doesn't matter. Am I missing something?
> BTW, why would one clone closures anyway?
>
> > […]
>
> This will get us into trouble IMHO, as it would not behave too well with
>  __get/__set and __call. I.e. if we have $foo->nosuchproperty() - should we
> call __get or __call? So far variables implemented through __get behave
> exactly like ones implemented through definition - but I don't understand
> how to reconcile it with this.
>
> I also don't like having special one-class check inside assignment operators
> just for this narrow function - it doesn't look like good generic code and I
> suspect for proper implementation may require instanceof check on each
> assignment - which would be really bad.
>
> > […]
>
> Of course it matters how (or, more precisely, where) the closure was created
> - isn't it the whole point of closure?
>
> > […]
>
> This is another thing - does it mean on each assignment we'd have to check
> if member function with same name doesn't exist? That might break some code
> in interesting ways too.

It will not be able to respect the inheritance rules as well (at least
how it is implemented currently) :

class A {
   public function plop(){}
}
class B extends A {}

$b = new B; $b->plop = function(){};
$b->plop(); //will still call A::plop().

And if by any chance there is a way to make that work, it will still
cause trouble with internal classes that checks for inherited methods
at instantiation only.
Looks like it would either introduce a lot of inconsistencies, or a
lot of edge cases to fix by adding exceptions in the code.

Regards,

> --
> Stanislav Malyshev, Zend Software Architect
> stas@zend.com   http://www.zend.com/
> (408)253-8829   MSN: stas@zend.com
>
> --
> 
> 
>
>
>
>



-- 
Etienne Kneuss
http://www.colder.ch

Men never do evil so completely and cheerfully as
when they do it from a religious conviction.
-- Pascal

---

## #42611 — Marcus Boerger — 2009-01-13T21:58:47+00:00

URL: https://externals.io/message/42592#42611 · In reply to: #42593

Hello Stanislav,

Tuesday, January 13, 2009, 12:07:31 AM, you wrote:

> Hi!

> > […]

> I'm not sure why would you expect this. If you have closure that has 
> some bound $var inside, and you use it in context which has another 
> $var, you don't expect that $var change to new scope's $var, do you?
> I always thought of closures as taking their variables and context with 
> them, not changing them each time caller changes.

Variables and this are two very different things in PHP and even more so
for closures. Because there this does not reflect the object itself but the
object it is bound to.

> Also, this adds very new thing to PHP - objects that change while being 
> assigned. I am not sure it is a good thing.

Well Closures are a brand new thing in PHP. So far we had nothing even
remotely close to the closures we have right now.

> > […]

> Besides the issue above with changing $this I'm not sure what would 
> proper clone do - i.e. by-val bound variables are by-val anyway, so it 
> shouldn't matter if they are cloned, and by-ref ones should be connected 
> anyway so again it doesn't matter. Am I missing something?
> BTW, why would one clone closures anyway?

I Was not at all speaking of static variables. In fact I suggest we keep
them exactly as they are. Which is probably what you want, based on what
you wrote. And in my opinion it also makes the most sense. A closure keeps
its state.

> > […]

> This will get us into trouble IMHO, as it would not behave too well with 
>   __get/__set and __call. I.e. if we have $foo->nosuchproperty() - 
> should we call __get or __call? So far variables implemented through 
> __get behave exactly like ones implemented through definition - but I 
> don't understand how to reconcile it with this.

Why would you call __get() here? Becasue I did that by mistake in my very
first mail? You clearly have a function call and thus you only go for
__call(). As of today you can already do:

function __call($name, $args) {
  if ($this->properties[$name] instanceof 'Closure') {
    return call_user_func_array($this->property[$name], $args);
  }
}

Now we already have callable properties - directly callable.

> I also don't like having special one-class check inside assignment 
> operators just for this narrow function - it doesn't look like good 
> generic code and I suspect for proper implementation may require 
> instanceof check on each assignment - which would be really bad.

No, becasue Closure cannot be derived as it is a final class. If we change
that later then we simply have to change the check to test for the handler.
We might want to do that anyway as it is faster.

> > […]

> Of course it matters how (or, more precisely, where) the closure was 
> created - isn't it the whole point of closure?

It matters how you bind static variables to it as they are taken from the
context. And by the binding you keep the context. Sure all right. But we
bind this in a completely different way.

And when I bind a closure to an object inside that object why should it be
different from an assignment outside the class? And it gets even better, if
you assign that closure to another object it gets private access to the
other classes members; plus you can bind it to the new classes private
members as well. This is a nightmare and plain wrong to me and the part
with accessing another classes private members without knowing will create
a very large WTF factor and conflicts with everythign we ever said about
visibility.

> > […]

> This is another thing - does it mean on each assignment we'd have to 
> check if member function with same name doesn't exist? That might break 
> some code in interesting ways too.

I don't see a reason for this. But people might differ. And at the end of
the day the problems arising from this are the least evil.


Best regards,
 Marcus

---

## #42613 — Stanislav Malyshev — 2009-01-13T23:15:00+00:00

URL: https://externals.io/message/42592#42613 · In reply to: #42611

Hi!

> > […]
> 
> Well Closures are a brand new thing in PHP. So far we had nothing even
> remotely close to the closures we have right now.

There are a lot of different features in PHP, that's not the reason to 
turn the engine into a salad of special cases and exceptions. That's why 
making Closure an object and having __invoke was a good idea - because 
it fits what the engine already does very well. Having special case just 
for one class doesn't fit it so well.

> you wrote. And in my opinion it also makes the most sense. A closure keeps
> its state.

I consider $this be a part of this state. Maybe if you really need it 
it'd be fine to do something like $closure->setThis($object)...

> Why would you call __get() here? Becasue I did that by mistake in my very

Imagine such code:

class Contains {
	private $_store;

	function __set($n, $v) {
		$this->_store[$n] = $v;
	}

	function __get($n) {
		return $this->_store[$n];
	}
}

Pretty standard class. Now imagine you do this:

$c = new Contains();
$c->foo = "bar";
echo $c->foo;

works well and basically you see Contains as regular object and couldn't 
care less it has handlers and not properties. Now this:

$c->bar = function() { }
$c->bar();

what happens here? You can't get the value of "bar" without calling 
__get and if you call __call instead that means you either lost $c->bar 
or you have two kinds of properties now - ones that call __get and ones 
that don't. I don't see how it is good.

> No, becasue Closure cannot be derived as it is a final class. If we change

Why it's a final class? Any special reason for that?

> It matters how you bind static variables to it as they are taken from the
> context. And by the binding you keep the context. Sure all right. But we
> bind this in a completely different way.

I see no reason to have two contexts in closure - one bound one way and 
another bound another way. I think context is a context - it's where the 
closure was created.

> different from an assignment outside the class? And it gets even better, if
> you assign that closure to another object it gets private access to the
> other classes members; plus you can bind it to the new classes private

That's the whole point of the closure - if you make object-bound closure 
you can pass accessors to private variables to external classes. If you 
don't want it - either don't access privates in your closure or make the 
closure static. The whole point of the closure is that you can keep the 
context with the closure and thus give other scope regulated access to 
your scope.

> I don't see a reason for this. But people might differ. And at the end of
> the day the problems arising from this are the least evil.

The least between what and what? I don't see any problem or "evil" with 
what we have now except for missing exotic feature of rebinding closures 
- which would be a huge WTF for me if all closures worked this way (I 
definitely expect closure to keep its context and not switch it each 
time I pass it around), but if there was a special way to make it work 
this way (as setThis mentioned above or any other way) and it would not 
conflict with other features and not require dirty hacks on the engine I 
wouldn't mind.
-- 
Stanislav Malyshev, Zend Software Architect
stas@zend.com   http://www.zend.com/
(408)253-8829   MSN: stas@zend.com

---

## #42615 — Xuefer — 2009-01-14T02:35:20+00:00

URL: https://externals.io/message/42592#42615 · In reply to: #42613

just a note about it
in javascript, "this" ($this in php) is a special variable in closure,
"this" is always bound to the "object" of "object.method(...)" when it
is called, whenever i want a "this" of closure creation time context,
i use:
var _this = this;
return function() { _this.prop = 123; _this.method(); }
so..

> I see no reason to have two contexts in closure - one bound one way and
> another bound another way
it's already 2 contexts in php: $this and $_LOCALSCOPE (which is not
available in user code). and now $_CLOSURE context
the reason you think there's only 1 context maybe because $this is
implemented in $_LOCALSCOPE['this'] = &$this in php internally. :)
> I think context is a context - it's where the closure was created.
true, the $_CLOSURE context

prototype can be useful in php. and like closure that ppl got used to
javascript version of closure/prototype, there should be no big
problem understanding it.

---

## #42616 — Ionut Gabriel Stan — 2009-01-14T11:54:17+00:00

URL: https://externals.io/message/42592#42616 · In reply to: #42613

> Hi!
>
> > […]
>
> There are a lot of different features in PHP, that's not the reason to
> turn the engine into a salad of special cases and exceptions. That's why
> making Closure an object and having __invoke was a good idea - because
> it fits what the engine already does very well. Having special case just
> for one class doesn't fit it so well.
>
> > […]
>
> I consider $this be a part of this state. Maybe if you really need it
> it'd be fine to do something like $closure->setThis($object)...
>
> > […]
>
> Imagine such code:
>
> class Contains {
> private $_store;
>
> function __set($n, $v) {
> $this->_store[$n] = $v;
> }
>
> function __get($n) {
> return $this->_store[$n];
> }
> }
>
> Pretty standard class. Now imagine you do this:
>
> $c = new Contains();
> $c->foo = "bar";
> echo $c->foo;
>
> works well and basically you see Contains as regular object and couldn't
> care less it has handlers and not properties. Now this:
>
> $c->bar = function() { }
> $c->bar();
>
> what happens here? You can't get the value of "bar" without calling
> __get and if you call __call instead that means you either lost $c->bar
> or you have two kinds of properties now - ones that call __get and ones
> that don't. I don't see how it is good.

That is one example of convoluted code that is already possible. If a 
developer creates such a mess is his fault.

As Marcus said, it is already possible to call properties. All we have 
to do is implement __call(). Not being forced to implement __call in 
cases where we want object augmentation with lambdas is just syntactic 
sugar. I agree though that a rebind()/setThis() method on the Closure 
object is needed, but $this should be rebound by default.

Auto-magically binding $this to the current object, whatever that may 
be, is a missing feature that requires a developer to pass the instance 
as an argument to that lambda.

class A
{
     protected $_lambdas = array();


     public function __set($name, $lambda)
     {
         $this->_lambdas[$name] = $lambda;
     }

     public function __call($lambda, $args)
     {
         $args = array_merge($this, $args);
         return call_user_func_array($this->_lambdas[$lambda], $args);
     }
}

$a = new A;
$a->foo = function($this) {
     var_dump($this);
};
$a->foo();


Now, the above code is already possible, but... by implementing callable 
properties a developer is spared the effort of implementing a __call() 
method. The only problem now is that by deciding to not implement 
__call() he loses a nice opportunity of passing the instance object and 
he's left with some ugly alternatives:

class B
{}

$b = new B;
$b->foo = function($this) {
     var_dump($this);
};

$b->foo($b);

// how would be the above call different than?
$foo = function($object) {
     var_dump($object);
}
$foo($b);

// Or would you believe this is just fine?
$b->foo = function() use ($b) {
     var_dump($b);
};
$b->foo();

Sooner or later, people would want that use statement to be dismissed 
for an auto-magically bound $this. It's also the problem of accessing 
protected and private members.

JavaScript does automatic binding of the "this" instance which is 
actually a key point in prototyping. Well, strictly speaking this is not 
prototyping, is augmentation. Adding members to the JS prototype object 
means that *any* existing and further instances will share those 
members. Augmentation is just about adding members to an existing 
instance. Real prototyping is though possible in PHP 5.3:

class A
{
     /**
      * Lambdas available to all instances
      */
     public static $lambda;

     public function __call($method, $args)
     {
         $method = self::$lambda;
         return call_user_func_array($method, $args);
     }
}

A::$lambda = function() {
     return 'foo';
};

$a1 = new A;
$a2 = new A;

echo $a1->lambda();
echo $a2->lambda();

The problem of binding $this appears again, but I believe this use case 
is much harder to solve because there's no $this in the moment we add 
lambdas to the class. Anyway, it's a point to consider.



> > […]
>
> Why it's a final class? Any special reason for that?
>
> > […]
>
> I see no reason to have two contexts in closure - one bound one way and
> another bound another way. I think context is a context - it's where the
> closure was created.
>
> > […]
>
> That's the whole point of the closure - if you make object-bound closure
> you can pass accessors to private variables to external classes. If you
> don't want it - either don't access privates in your closure or make the
> closure static. The whole point of the closure is that you can keep the
> context with the closure and thus give other scope regulated access to
> your scope.

In this particular case I think having callable properties has less to 
do with closures (I mean capturing context, not lambdas) and more to do 
with extending functionality of existing classes and objects without a 
need for creating additional classes. It's also about overriding 
existent behavior.

In JavaScript, if you don't have a String.trim() function you add it to 
the prototype. From that moment on, all your strings have a `trim()` method:

String.prototype.trim = function() {};

Of course, this is nice for primitive types that have some form of 
syntactic sugar representation, quotes in case of strings. So now I'm 
able to do:

var trimmed = " has spaces ".trim();

This is of course not the case with PHP, but as I said, this feature has 
less to do with closures.


> > […]
>
> The least between what and what? I don't see any problem or "evil" with
> what we have now except for missing exotic feature of rebinding closures
> - which would be a huge WTF for me if all closures worked this way (I
> definitely expect closure to keep its context and not switch it each
> time I pass it around), but if there was a special way to make it work
> this way (as setThis mentioned above or any other way) and it would not
> conflict with other features and not require dirty hacks on the engine I
> wouldn't mind.

---

## #42617 — Stanislav Malyshev — 2009-01-14T16:29:02+00:00

URL: https://externals.io/message/42592#42617 · In reply to: #42616

Hi!

> That is one example of convoluted code that is already possible. If a 
> developer creates such a mess is his fault.

"Convoluted"? "Mess"? Are you kidding me? It's standard usage of access 
handlers.
-- 
Stanislav Malyshev, Zend Software Architect
stas@zend.com   http://www.zend.com/
(408)253-8829   MSN: stas@zend.com

---

## #42622 — Ionut Gabriel Stan — 2009-01-14T21:59:12+00:00

URL: https://externals.io/message/42592#42622 · In reply to: #42617

Hi,


> Hi!
>
> > […]
>
> "Convoluted"? "Mess"? Are you kidding me? It's standard usage of 
> access handlers.
I don't understand how that could be standard when the example was about 
calling overloaded properties, which isn't yet possible in the language, 
as you vigilantly observed.

Now, regardless whether is convoluted or not, you must agree that is 
better having callable properties in the language and documenting that 
this won't apply for overloaded properties. In the end you don't really 
need callable overloaded properties as a developer already has access to 
the internals of a class, thus __call() is all he needs to implement 
them (there would be at least a magic call anyway). It's a trade off but 
a worthy one in my opinion. Just as right now it is being documented 
that in order to call a lambda assigned to an instance property you need 
a temporary variable, it could be easily documented that one should not 
expect callable overloaded properties and must instead implement __call 
beside the standard __get/__set.
It's a WTF but a smaller one this time. Anyway, there may be stronger 
arguments against so I'm interested in your opinion.

Thanks,
I. Stan

---

## #42623 — Stanislav Malyshev — 2009-01-14T22:11:04+00:00

URL: https://externals.io/message/42592#42623 · In reply to: #42622

Hi!

> Now, regardless whether is convoluted or not, you must agree that is 
> better having callable properties in the language and documenting that 
> this won't apply for overloaded properties. In the end you don't really 

I do not see any aspect in which it would be better.

> need callable overloaded properties as a developer already has access to 

Having features in the language that do not work together is usually a 
bad idea. Developer using overloads would expect it to work in most 
cases where properties work, and if this prototyping design can not do 
it I think it is a sign more work is needed to solve it before we can 
add it.
-- 
Stanislav Malyshev, Zend Software Architect
stas@zend.com   http://www.zend.com/
(408)253-8829   MSN: stas@zend.com

---

## #42633 — Lukas Kahwe Smith — 2009-01-15T09:56:01+00:00

URL: https://externals.io/message/42592#42633 · In reply to: #42623

Hi

I have tried to catch up to the discussion yesterday evening. I must  
admit its not very trivial for me to understand the entire scope of  
the issues. I am especially worried about things becoming too magical  
(although in general I am pro giving end users all the power in the  
world). At this point I am beginning to wonder if we maybe should drop  
any special OO handling from closures for now and leave it to the next  
bigger release to decide if to readd it.

We have worked through the challenge of getting namespaces worked out  
in 5.3, adding yet another increasingly heavy feature to the syntax  
would delay us if we really want to make sure we get it right.  
Screwing up would get us into a world of hurt and to me the main use  
case we wanted to address was making it easier to define callbacks for  
our various internal functions.

This is just my "managament" level view point given the discussion at  
this stage and the goal to get PHP 5.3 out the door without delay from  
any feature (since we have enough features to release even if we  
remove one or two features).

regards,
Lukas

---

## #42636 — Giovanni Giacobbi — 2009-01-15T12:31:25+00:00

URL: https://externals.io/message/42592#42636 · In reply to: #42633

> 
> We have worked through the challenge of getting namespaces worked out  
> in 5.3, adding yet another increasingly heavy feature to the syntax  
> would delay us if we really want to make sure we get it right.  
> Screwing up would get us into a world of hurt and to me the main use  
> case we wanted to address was making it easier to define callbacks for  
> our various internal functions.
> 

I was wondering, why don't you simply mark the feature as "experimental", so people that use it know that it might change unexpectedly from one version to another, breaking their scripts. Something similar to the Linux Kernel features approach.

I've never seen this approach used in PHP development process, I've always been seeing the "feature freeze -> support for a long time -> deprecate -> remove in the next major version" approach. Marking a particular language feature as experimental would allow you to drop it or to change it without notice even in a patchlevel release (5.3.1), resulting in a way quicker and more dynamic development process.

The benefits? Nobody (but me...) would install an unstable version of PHP in a production environment, but probably some people would taste an experimental feature included in a stable version.

Just my 2 cents.
Regards,

-- 
Giovanni Giacobbi

---

## #42637 — david.zuelke@bitextender.com — 2009-01-15T16:07:35+00:00

URL: https://externals.io/message/42592#42637 · In reply to: #42611

Am 13.01.2009 um 22:58 schrieb Marcus Boerger:

> > […]
>
> > […]
>
> Why would you call __get() here? Becasue I did that by mistake in my  
> very
> first mail? You clearly have a function call and thus you only go for
> __call(). As of today you can already do:
>
> function __call($name, $args) {
>  if ($this->properties[$name] instanceof 'Closure') {
>    return call_user_func_array($this->property[$name], $args);
>  }
> }
>
> Now we already have callable properties - directly callable.

1. method
2. __call()
3. property
4. __get()

that would be a reasonable calling order, or:

1. method
2. property
3. __call()
4. __get()

In any case, a "real" method (existing one or __call() overload)  
should have precedence over a closure in a property.

Wouldn't that work?

- David

---

## #42672 — Lukas Kahwe Smith — 2009-01-17T05:44:51+00:00

URL: https://externals.io/message/42592#42672 · In reply to: #42637

Hi,

Ok, my proposal to drop OO support from Closures was exactly embraced.  
All I want you guys to think about is how you want to deal with this  
in terms of the PHP 5.3 release. If no decision is found and  
implemented over the weekend, this topic will essentially cement the  
need for an additional beta .. or at worse staying at alpha.

I am playing a frisbee tournament this weekend, so I hope by Sunday  
evening there is a decision on how to proceed in regards to Closures/ 
Prototypes. Depending on what that decision is, we will figure out  
some schedule.

The current plan would see a freeze on Monday, giving us Tuesday to do  
build fixing, Wednesday to package and Thursday to release.

regards,
Lukas

---

## #42679 — Marcus Boerger — 2009-01-17T20:26:30+00:00

URL: https://externals.io/message/42592#42679 · In reply to: #42617

Hello Stanislav,

Wednesday, January 14, 2009, 5:29:02 PM, you wrote:

> Hi!

> > […]

> "Convoluted"? "Mess"? Are you kidding me? It's standard usage of access 
> handlers.

It is a mess right now. You assign a closure to another method and get
access to the original owners private members. That is not only unexpected
and contradicting anything that any oyther language ever but but also
violates our very own basic ideas. That is what I call a mess.

Best regards,
 Marcus

---

## #42690 — Christian Seiler — 2009-01-18T22:58:29+00:00

URL: https://externals.io/message/42592#42690 · In reply to: #42679

Hi Marcus,

> > […]
> 
> It is a mess right now. You assign a closure to another method and get
> access to the original owners private members. That is not only unexpected
> and contradicting anything that any oyther language ever but but also
> violates our very own basic ideas. That is what I call a mess.

You could also call Javascript's behaviour confusing. A closure is per
definition a function that encloses its scope at creation time. E.g. if
you have the following (in Javascript, PHP, doesn't matter):

var foo;
var closure = function () {
	alert (foo);
};

The current scope variable foo is inherited. The question is: Why
shouldn't the same also happen for the variable this? In the closures
implementatios Dmitry and I designed for PHP, it does. Admittedly, $this
is a special variable because it's implicitly available in normal
methods and thus we decided that for closures you don't need to do "use
($this)" either.

So the question is: Why does Javascript change the pointer to the this
variable upon calling a method? The answer is simple: Because there is
NO OTHER WAY to define object methods in Javascript. You *always* have
to use object.method = function () { }; or Something.prototype.method =
... in order to define a callable method. There is no other way. Because
of that, Javascript defines the behaviour with $this.

PHP, on the other hand, since it already does have a method for creating
normal class methods (simply define them in the class { } block), does
not need such a mechanism for normal OOP.

Also, implementing this in PHP may give quite some headaches. Take for
example the following code:

interface Some_Filter {
  public function accept ($value);
}

class Closure_Filter implements Some_Filter {
  private $closure;
  public function __construct (Closure $closure) {
    $this->closure = $closure;
  }
  public function accept ($value) {
    // Or something similar, see below
    return call_user_func ($this->closure, $value);
  }
}

class Foo {
  private $min, $max;

  public function bar () {
    $filter = new Closure_Filter (function ($value) {
      return $value >= $this->min && $value <= $this->max;
    });
    $data = $something->doSomethingElse ($filter, $data);
  }
}

Now, basically, the idea behind this code should be clear: We want to
define a filter, there's an interface for that filter that any class may
define and there's a simple wrapper class for Closures for filters that
are supposed to be extremely simple. I don't think this example is
convoluted, one could easily imagine a similar design in the real word
(probably a bit more complex, but nevertheless).

The filter closure is now defined in the class Foo. Thus one would
assume that the closure is bound to the $this of the Foo object (once
created). But since that closure is passed to the constructor of the
Closure_Filter class, the $this would be rebound according to your
proposal. Thus, when invoking the method, the closure would now try to
access the ->min and ->max properties of Closure_Filter class - which is
clearly not the intention.

Of course, there are possibilites to circumvent that: 1) Copy the min
and max properties to local scope and bind them with use() to the
closure. Or 2) Don't store the closure directly inside a property of the
Closure_Filter class but in an array so $this doesn't get rebound. But
clearly, in my eyes, that is some kind of hackish workaround that really
sucks.

Also, with the implementation Dmitry and I wrote, it is very clear what
the semantics are $this: It is always bound at creation time and that's
it. Just to make a comparison:

// Variant 1:
return call_user_func ($this->closure, $value);
// Variant 2:
$closure = $this->closure;
return $closure ($value);
// Variant 3:
return $this->closure->__invoke ($value);
// Variant 4:
return $this->closure ($value);

Now, the original implementation:
  Variant 1: $this bound to Foo class
  Variant 2: $this bound to Foo class
  Variant 3: $this bound to Foo class
  Variant 4: doesn't work, because methods and properties have a
             different namespace

Now, an implementation where *all* four variants bind to the
Closure_Filter class:
  Variant 1: $this bound to Closure_Filter class
      -> Inconsistent: call_user_func ($this->normal_method) will first
                       cause "undefined property" and then "invalid
                       callback" errors
  Variant 2: $this bound to Closure_Filter class
      -> Hmm, so this basically allows for the following code:
               $closure = function ...;
               $object->closure = $closure; // MAGIC happens!
               $closure = $object->closure; // $closure changed - WTF?!
  Variant 3: $this bound to Closure_Filter class
      -> Ok, this really doesn't matter either way, using __invoke
         directly looks a bit weird anyway.
  Variant 4: $this bound to Closure_Filter class
      -> Calling properties directly will certainly cause resolution
         order headaches. Since that was the MAIN point on the list that
         was discussed before my posting you will have to admit it at
         least is not obvious what the resolution order should be.

Ok, you could say *ONLY* variant 4 should be added with dynamic and
temporary (i.e. call-time and for the duration of the call) rebinding of
the $this context. But that would also cause confusion: Why should $this
for the *same* property on some occasions a first object and on some
another? It doesn't make any sense!

Now, I would call this certainly a bigger mess than the inconsistency
wrt. Javascript. Since PHP is already different from Javascript (access
modifiers, "normal" object methods, different namespaces for methods and
properties), I don't really see the point in forcing something which
will create problems with the concepts PHP already has.

----------------------- snip ------------------

However, having said that, I may have a solution which will make
everybody (more or less at least) happy:

Since the main problem of re-binding closures to different objects is
the obscure magic just by assignment, why not make that magic "public"?

I.e.: Add a method bindTo() to the Closure class which returns an
identical copy of the closure (same bound variables etc.) with the
EXCEPTION that the new variables are already bound. This allows for
prototyping in the way that you want it BUT ensures that no silent magic
occurs that creates problems.

Example:
$func = function ($a, $b) {
  return $a + $b + $this->bias;
};
$object->add = $func->bindTo ($object);

Additionally, a static method bind() could be added for direct assignments:

$object->add = Closure::bind ($object, function ($a, $b) {
  return $a + $b + $this->bias;
});

The bindTo/bind functions could also check the current class scope and
ensure that the class scope of the newly bound closure has the same
access level to the object as the current class - that would enforce
access modifiers. Whether or not we want that is probably a matter of
debate.

Another idea which *could* be discussed (I'm not sure about it myself)
is that if you add variant 4 from above (i.e. calling object properties
like methods directly) - which you probably want to do if you want to
allow $this rebinding - and we have finally figured out some sane
resolution rules, one could also add a `E_WARNING` message when the $this
pointer of the closure does not match the $this pointer of the object
for which the closure is called as a method. So, for example:

$closure = function () { return $this->value; };
$object->get1 = $closure;
$object->get2 = $closure->bindTo ($object);

call_user_func ($object->get1);
call_user_func ($object->get2);
$f = $object->get1; $f ();
$f = $object->get2; $f ();
$object->get1->__invoke ();
$object->get2->__invoke ();
  // -> No warnings
  //       BECAUSE (!) this syntax makes it clear to the user that
  //       he is calling *some* closure, but not necessarily a closure
  //       bound to the specific object
$object->get1 ();
  // -> Warning: Closure called directly but object scope does
  //    not match object closure is being called for!
  // -> HOWEVER, execute the closure and DON'T rebind it
$object->get2 ();
  // -> No warning (match)

The check should of course be intelligent enough to detect the
following correctly:

$this->foo = function () { ... };
$this->foo ();
  // -> No warning (match, since assigned from inside the own object)

------------------ snip again --------------------

So, to sum up my posting:

1. Stance on direct method calling $foo->closure_property ()

       - As long as you figure out some sane and consistent resolution
         rules: Fine with me.

2. Stance on *automatic* re-binding of $this

       - Really big convoluted mess
       - PHP already does things differently from Javascript, has
         different concepts.
           => I'm against it.

3. Alternative proposal for making re-binding possible but making
   sure this is done explicitly:

       - Figure out some sane resolution rules
       - Closure::bind and Closure->bindTo

4. Additional proposal to 3:

       - Enforce class scope and thus access modifiers when using
         Closure::bind / Closure->bindTo

5. Additional propsoal to 3:

       - Warning when using direct-calling and the closure is not
         bound to the object for which the closure is called.

Regards,
Christian

---

## #42694 — Stanislav Malyshev — 2009-01-19T08:32:09+00:00

URL: https://externals.io/message/42592#42694 · In reply to: #42679

Hi!

> It is a mess right now. You assign a closure to another method and get
> access to the original owners private members. That is not only unexpected

Could you give a code example? I'm not sure I understand what you mean 
by access (or "assign closure to a method" for that matter) - if access 
provided by the closure, it's exactly the intent of the closure. If some 
other access, then please explain which one.
-- 
Stanislav Malyshev, Zend Software Architect
stas@zend.com   http://www.zend.com/
(408)253-8829   MSN: stas@zend.com

---

## #42702 — Marcus Boerger — 2009-01-19T11:47:28+00:00

URL: https://externals.io/message/42592#42702 · In reply to: #42690

Hello Christian,

Sunday, January 18, 2009, 11:58:29 PM, you wrote:

> Hi Marcus,

> > […]

> You could also call Javascript's behaviour confusing. A closure is per

And I could say that what the two of you designed ofr PHP is not a design
but a very confusing incoherent implementation that is based on the lack
of being able to get support for something else in the underlying c
implementation. You took somethign very special and made it behave somewhat
different making it even more specific and different from anyone's
expectations, excluding people that understand the underlying c level
issues.

Either way, we should imo, simply disable $this for clusresm get and get
rid of any dynamic class binding mess or make them work. Doing a lot of
unexpected behavior is in my opinion very very bad.

> definition a function that encloses its scope at creation time. E.g. if
> you have the following (in Javascript, PHP, doesn't matter):

> var foo;
> var closure = function () {
>         alert (foo);
> };

> The current scope variable foo is inherited. The question is: Why
> shouldn't the same also happen for the variable this? In the closures
> implementatios Dmitry and I designed for PHP, it does. Admittedly, $this
> is a special variable because it's implicitly available in normal
> methods and thus we decided that for closures you don't need to do "use
> ($this)" either.

> So the question is: Why does Javascript change the pointer to the this
> variable upon calling a method? The answer is simple: Because there is
> NO OTHER WAY to define object methods in Javascript. You *always* have
> to use object.method = function () { }; or Something.prototype.method =
> ... in order to define a callable method. There is no other way. Because
> of that, Javascript defines the behaviour with $this.

> PHP, on the other hand, since it already does have a method for creating
> normal class methods (simply define them in the class { } block), does
> not need such a mechanism for normal OOP.

> Also, implementing this in PHP may give quite some headaches. Take for
> example the following code:

> interface Some_Filter {
>   public function accept ($value);
> }

> class Closure_Filter implements Some_Filter {
>   private $closure;
>   public function __construct (Closure $closure) {
>     $this->closure = $closure;
>   }
>   public function accept ($value) {
>     // Or something similar, see below
>     return call_user_func ($this->closure, $value);
>   }
> }

> class Foo {
>   private $min, $max;

>   public function bar () {
>     $filter = new Closure_Filter (function ($value) {
>       return $value >= $this->min && $value <= $this->max;
>     });
>     $data = $something->doSomethingElse ($filter, $data);
>   }
> }

> Now, basically, the idea behind this code should be clear: We want to
> define a filter, there's an interface for that filter that any class may
> define and there's a simple wrapper class for Closures for filters that
> are supposed to be extremely simple. I don't think this example is
> convoluted, one could easily imagine a similar design in the real word
> (probably a bit more complex, but nevertheless).

> The filter closure is now defined in the class Foo. Thus one would
> assume that the closure is bound to the $this of the Foo object (once
> created). But since that closure is passed to the constructor of the
> Closure_Filter class, the $this would be rebound according to your
> proposal. Thus, when invoking the method, the closure would now try to
> access the ->min and ->max properties of Closure_Filter class - which is
> clearly not the intention.

> Of course, there are possibilites to circumvent that: 1) Copy the min
> and max properties to local scope and bind them with use() to the
> closure. Or 2) Don't store the closure directly inside a property of the
> Closure_Filter class but in an array so $this doesn't get rebound. But
> clearly, in my eyes, that is some kind of hackish workaround that really
> sucks.

> Also, with the implementation Dmitry and I wrote, it is very clear what
> the semantics are $this: It is always bound at creation time and that's
> it. Just to make a comparison:

> // Variant 1:
> return call_user_func ($this->closure, $value);
> // Variant 2:
> $closure = $this->closure;
> return $closure ($value);
> // Variant 3:
> return $this->closure->__invoke ($value);
> // Variant 4:
> return $this->closure ($value);

> Now, the original implementation:
>   Variant 1: $this bound to Foo class
>   Variant 2: $this bound to Foo class
>   Variant 3: $this bound to Foo class
>   Variant 4: doesn't work, because methods and properties have a
>              different namespace

> Now, an implementation where *all* four variants bind to the
> Closure_Filter class:
>   Variant 1: $this bound to Closure_Filter class
>       -> Inconsistent: call_user_func ($this->normal_method) will first
>                        cause "undefined property" and then "invalid
>                        callback" errors
>   Variant 2: $this bound to Closure_Filter class
>       -> Hmm, so this basically allows for the following code:
>                $closure = function ...;
>                $object->closure = $closure; // MAGIC happens!
>                $closure = $object->closure; // $closure changed - WTF?!
>   Variant 3: $this bound to Closure_Filter class
>       -> Ok, this really doesn't matter either way, using __invoke
>          directly looks a bit weird anyway.
>   Variant 4: $this bound to Closure_Filter class
>       -> Calling properties directly will certainly cause resolution
>          order headaches. Since that was the MAIN point on the list that
>          was discussed before my posting you will have to admit it at
>          least is not obvious what the resolution order should be.

> Ok, you could say *ONLY* variant 4 should be added with dynamic and
> temporary (i.e. call-time and for the duration of the call) rebinding of
> the $this context. But that would also cause confusion: Why should $this
> for the *same* property on some occasions a first object and on some
> another? It doesn't make any sense!

> Now, I would call this certainly a bigger mess than the inconsistency
> wrt. Javascript. Since PHP is already different from Javascript (access
> modifiers, "normal" object methods, different namespaces for methods and
> properties), I don't really see the point in forcing something which
> will create problems with the concepts PHP already has.

> ----------------------- snip ------------------

> However, having said that, I may have a solution which will make
> everybody (more or less at least) happy:

> Since the main problem of re-binding closures to different objects is
> the obscure magic just by assignment, why not make that magic "public"?

> I.e.: Add a method bindTo() to the Closure class which returns an
> identical copy of the closure (same bound variables etc.) with the
> EXCEPTION that the new variables are already bound. This allows for
> prototyping in the way that you want it BUT ensures that no silent magic
> occurs that creates problems.

> Example:
> $func = function ($a, $b) {
>   return $a + $b + $this->bias;
> };
> $object->add = $func->bindTo ($object);

> Additionally, a static method bind() could be added for direct assignments:

> $object->add = Closure::bind ($object, function ($a, $b) {
>   return $a + $b + $this->bias;
> });

> The bindTo/bind functions could also check the current class scope and
> ensure that the class scope of the newly bound closure has the same
> access level to the object as the current class - that would enforce
> access modifiers. Whether or not we want that is probably a matter of
> debate.

> Another idea which *could* be discussed (I'm not sure about it myself)
> is that if you add variant 4 from above (i.e. calling object properties
> like methods directly) - which you probably want to do if you want to
> allow $this rebinding - and we have finally figured out some sane
> resolution rules, one could also add a `E_WARNING` message when the $this
> pointer of the closure does not match the $this pointer of the object
> for which the closure is called as a method. So, for example:

> $closure = function () { return $this->value; };
> $object->get1 = $closure;
> $object->get2 = $closure->bindTo ($object);

> call_user_func ($object->get1);
> call_user_func ($object->get2);
> $f = $object->get1; $f ();
> $f = $object->get2; $f ();
> $object->get1->__invoke ();
> $object->get2->__invoke ();
>   // -> No warnings
>   //       BECAUSE (!) this syntax makes it clear to the user that
>   //       he is calling *some* closure, but not necessarily a closure
>   //       bound to the specific object
> $object->get1 ();
>   // -> Warning: Closure called directly but object scope does
>   //    not match object closure is being called for!
>   // -> HOWEVER, execute the closure and DON'T rebind it
> $object->get2 ();
>   // -> No warning (match)

> The check should of course be intelligent enough to detect the
> following correctly:

> $this->foo = function () { ... };
> $this->foo ();
>   // -> No warning (match, since assigned from inside the own object)

> ------------------ snip again --------------------

> So, to sum up my posting:

> 1. Stance on direct method calling $foo->closure_property ()

>        - As long as you figure out some sane and consistent resolution
>          rules: Fine with me.

> 2. Stance on *automatic* re-binding of $this

>        - Really big convoluted mess
>        - PHP already does things differently from Javascript, has
>          different concepts.
>            => I'm against it.

> 3. Alternative proposal for making re-binding possible but making
>    sure this is done explicitly:

>        - Figure out some sane resolution rules
>        - Closure::bind and Closure->bindTo

> 4. Additional proposal to 3:

>        - Enforce class scope and thus access modifiers when using
>          Closure::bind / Closure->bindTo

> 5. Additional propsoal to 3:

>        - Warning when using direct-calling and the closure is not
>          bound to the object for which the closure is called.

> Regards,
> Christian




Best regards,
 Marcus

---

## #42703 — Marcus Boerger — 2009-01-19T11:57:21+00:00

URL: https://externals.io/message/42592#42703 · In reply to: #42694

Hello Stanislav,

Monday, January 19, 2009, 9:32:09 AM, you wrote:

> Hi!

> > […]

> Could you give a code example? I'm not sure I understand what you mean 
> by access (or "assign closure to a method" for that matter) - if access 
> provided by the closure, it's exactly the intent of the closure. If some 
> other access, then please explain which one.

class Foo {
  private $myVeryOwnData;
  function bla {
    $this->bigMEss = function () { return $this->myVeryOwnData; }
  }
}

$o = new Foo;
$f = $o->bla;

echo $f();

class Bar {
  function baz{} {
    $this->xyz = $o->bla;  // or $f;
    // I am very sorry but I would expect the closure to rebind $this as
    // $this always points to the bound object. And how is this different?
    // If the different is that the closure is already bound and that is
    // what you want, then we need ways to do just that. And not inventing
    // new ways to deal with $this.
  }
}


$onother = new stdClass;
$another->blabla = $f;   // yet again a very unexpected $this.

If this really was to be bound to a $this at the creation, then we'd put it
into the scope binding list and not have it be handled implicitly. But then
we cannot do that with the current c level api. So instead you created
brand new rules, which unfortunately is the PHP way.

So how would I copy a closure instead of rebinding it?

I would use PHP's current established semantics for that. That is I'd do:

$this->closure = clone $closure;
$this->closure = $closure->copy();

How would I prevent automatic $this binding?

$closure = static function()....


> -- 
> Stanislav Malyshev, Zend Software Architect
> stas@zend.com   http://www.zend.com/
> (408)253-8829   MSN: stas@zend.com




Best regards,
 Marcus

---

## #42708 — Stanislav Malyshev — 2009-01-19T17:05:12+00:00

URL: https://externals.io/message/42592#42708 · In reply to: #42703

Hi!

> class Foo {
>   private $myVeryOwnData;
>   function bla {
>     $this->bigMEss = function () { return $this->myVeryOwnData; }
>   }
> }

This is not a "mess" - this is *exactly* what closures are for. If you 
don't want this function to be able to access private variables - do not 
put code that accesses private variables there! That's like saying this 
code is a "mess":

class Foo {
   private $myVeryOwnData;
   public function getData() {
     return $this->myVeryOwnData;
   }
}

because you can do this:

$a = new Foo();
echo $a->getData();

Oh horror!! It accessed private data!! Because you explicitly told it to 
access it, yes. What did you expect if you provide public method to 
access private data?

>     // I am very sorry but I would expect the closure to rebind $this as
>     // $this always points to the bound object. And how is this different?

I am very sorry but your expectation is wrong. There's no reason for 
closures to magically rebind, and if some particular language, due to 
limitations of its design, has this weird WTF inside, it's a problem 
that we don't have to carry on into PHP. If you created a closure, you 
got context. That's the whole point of closure. $this is part of the 
context. If for some reason you need WTF-closures that keep half of the 
context from where they were created and half from where they were 
called, you may create it, but regular closures shouldn't do that.
-- 
Stanislav Malyshev, Zend Software Architect
stas@zend.com   http://www.zend.com/
(408)253-8829   MSN: stas@zend.com

---

## #42723 — Lukas Kahwe Smith — 2009-01-20T11:54:34+00:00

URL: https://externals.io/message/42592#42723 · In reply to: #42708

Hi,

maybe an IRC meeting is the easiest way to come to an agreement. How  
about tomorrow evening 21:00 CEST in #php.closures on freenode?

regards.
Lukas

---

## #42731 — Christian Seiler — 2009-01-20T17:41:51+00:00

URL: https://externals.io/message/42592#42731 · In reply to: #42723

Hi,

> maybe an IRC meeting is the easiest way to come to an agreement. How
> about tomorrow evening 21:00 CEST in #php.closures on freenode?

Just for clarification: I assume you mean Wednesday, January 21st, 19:00
UTC (CEST == UTC+2) and thus 20:00 CET? Would be fine with me.

Regards,
Christian

---

## #42733 — Stanislav Malyshev — 2009-01-20T20:00:55+00:00

URL: https://externals.io/message/42592#42733 · In reply to: #42723

Hi!

> maybe an IRC meeting is the easiest way to come to an agreement. How 
> about tomorrow evening 21:00 CEST in #php.closures on freenode?

ok
-- 
Stanislav Malyshev, Zend Software Architect
stas@zend.com   http://www.zend.com/
(408)253-8829   MSN: stas@zend.com

---

## #42739 — david.zuelke@bitextender.com — 2009-01-21T09:04:28+00:00

URL: https://externals.io/message/42592#42739 · In reply to: #42731

Am 20.01.2009 um 18:41 schrieb Christian Seiler:

> Hi,
>
> > […]
>
> Just for clarification: I assume you mean Wednesday, January 21st,  
> 19:00
> UTC (CEST == UTC+2) and thus 20:00 CET? Would be fine with me.

I'm pretty confident he didn't mean summer time, so it's likely 21:00  
CET or 20:00 UTC.

---

## #42740 — Lukas Kahwe Smith — 2009-01-21T09:40:38+00:00

URL: https://externals.io/message/42592#42740 · In reply to: #42739

> Am 20.01.2009 um 18:41 schrieb Christian Seiler:
>
> > […]
>
> I'm pretty confident he didn't mean summer time, so it's likely  
> 21:00 CET or 20:00 UTC.

actually i did not think and it was just a random suggestion :)
since Christian wasn't forceful enough to settle things on a time,  
lets make it 21:00 CET or 20:00 UTC, tonight.

the channel is already open and people are ideling in there. however i  
would suggest that most of the talking should be done by the key  
people involved (marcus, stas, dmitry, christian, stan). other people  
are of course also invited to participate, but in order to let the  
discussion on irc to not go totally crazy it might be better that  
people pick their favorite of the 5 and just PM them with their  
thoughts, so that they can then relay them. for this purpose people  
will need a registered account on freenode IIRC. but there are no  
official rules .. so when in doubt common sense/courtesy rules :)

regards,
Lukas

PS: i will probably not participate .. though i will be idleing in the  
channel.

---

Next page: https://externals.io/message/42592.md?page=2
