Re: [PHP-DEV] [RFC] prototyping

2009-01-22 Thread Dmitry Stogov

Hi Marcus,

I've just got an idea how prototyping may be implemented without magic 
you solution had. We can use a special function


function attach_method($object, $name, $closure);

This function should clone the $closure bind $this of clone of $closure 
to $object and assign it into $object-name (the original $closure 
should be unchanged).


However it won't make possible to call it as $object-name() anyway.

Also, it's a question what should attach_method() do if $closure already 
has $this (rebind it or throw an exception).


Thanks. Dmitry.

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



Re: [PHP-DEV] [RFC] Object extension, $this binding of closures, chat results (was: Re: [PHP-DEV] [RFC] prototyping)

2009-01-22 Thread Larry Garfield
On Thursday 22 January 2009 8:21:28 am Christian Seiler wrote:
 Hi everybody,

 We had that chat that Lukas announced yesterday and I promised Lukas to
 sum up the results of that chat.

 Problem was: There were only four people really there: Stas, Lukas,
 David and me. Lukas was interested in getting results in order to be
 able to release PHP 5.3 beta 1, Stas and I basically agreed on
 everything and unfortunately David didn't stay long enough in order to
 actually have a real discussion.

 I'm not assigning blame here for not coming to anyone, I just wanted to
 make clear that we actually couldn't reach a consensus - or well,
 rather, Stas and I could but I don't think that's the way it should be.
 However, Lukas wants to release 5.3 beta 1 and I can really understand
 him that he doesn't want to drag this out infinitely.

 I've written up the results of the discussion I had with Stas in the
 Wiki for everyone to read. I hope there's enough structure in it to make
 the main points clear. Please read it thoroughly before replying on-list
 in order to actually have a constructive dialogue.

 Here it is: http://wiki.php.net/rfc/closures/object-extension

IMO, a very large part of the problem is the implicit binding of $this when a 
closure happens to be defined inside a method of a class.  Every other variable 
that the closure inherits needs to be defined explicitly; that not only helps 
the parser but helps human readers.  Having $this be magically bound seems 
like a cause for confusion later on down the road.

That said, I very much like the proposal given in the RFC.  Rebinding of a 
closure should be an explicit operation that a future reader of the code can 
visually see and therefore know about.  That removes any potential WTFs when 
$this is suddenly $that even though you didn't mean for it to be.

Regarding the details, wherein lives the devil:

- If a closure is bound to an object and does NOT make use of $this, do we 
still want to throw a warning if it is called?  In that case the binding is 
irrelevant anyway.  (That goes back to the point about an implicit initial 
bind, which I am still not convinced is wise.)

- IMO, once a closure has been bound to an object, its $this should have all 
the same access as a method defined literally on that object's class.  That is, 
it should have private/protected access the same as a normal method.

- I am a little unclear on what the expected cloning behavior is.  Do closures 
have a clone method?  Take the following example:

class A {
  function getClosure() {
$var = new Foo();
return function() use ($var) {
  return $var-something;
}
  }
}

$a = new A;
$o = new stdClass();
$closure = $a-getClosure();
$o-foo = $closure-bindTo($o);

Now, are $closure-var and $o-foo-var the same object or no?  I'm assuming 
they are from the RFC, but then how do you implement a deep clone of the 
closure on binding if you need to?

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

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



Re: [PHP-DEV] [RFC] prototyping

2009-01-21 Thread David Zülke

Am 20.01.2009 um 18:41 schrieb Christian Seiler:


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.


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

smime.p7s
Description: S/MIME cryptographic signature


Re: [PHP-DEV] [RFC] prototyping

2009-01-21 Thread Lukas Kahwe Smith


On 21.01.2009, at 10:04, David Zülke wrote:


Am 20.01.2009 um 18:41 schrieb Christian Seiler:


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.


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.

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



Re: [PHP-DEV] [RFC] prototyping

2009-01-20 Thread Lukas Kahwe Smith

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

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



Re: [PHP-DEV] [RFC] prototyping

2009-01-20 Thread Christian Seiler
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

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



Re: [PHP-DEV] [RFC] prototyping

2009-01-20 Thread Stanislav Malyshev

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
s...@zend.com   http://www.zend.com/
(408)253-8829   MSN: s...@zend.com

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



Re: [PHP-DEV] [RFC] prototyping

2009-01-19 Thread Stanislav Malyshev

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
s...@zend.com   http://www.zend.com/
(408)253-8829   MSN: s...@zend.com

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



Re: [PHP-DEV] [RFC] prototyping

2009-01-19 Thread Marcus Boerger
Hello Christian,

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

 Hi Marcus,

 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.

 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 

Re: [PHP-DEV] [RFC] prototyping

2009-01-19 Thread Marcus Boerger
Hello Stanislav,

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

 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.

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
 s...@zend.com   http://www.zend.com/
 (408)253-8829   MSN: s...@zend.com




Best regards,
 Marcus


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



Re: [PHP-DEV] [RFC] prototyping

2009-01-19 Thread Christian seiler

Hi Marcus,



 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.



Huh? The current implementation is by design, not because of any

limitations on C level. If you are refering to the following sentence in

your answer to Stanislav:



 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.



The fact is: We could very easily. We decided against it (it's somewhere in

the internals archives from over half a year ago, I'm too lazy to look for

it).



So, if I get you, you say: If $this is only bound at closure creation time,

then you should add $this to use(), i.e.:



$f = function () use ($this) { ... };



Well, if you rather want that syntax instead of static/non-static, you

could simple edit zend_compile.c and do the following:



 - change zend_do_begin_lambda_function_declaration: set fn_flags to

   ZEND_ACC_STATIC by default (and remove the is_static parameter

   from that function)

 - change zend_do_fetch_lexical_variable: In the case $this was

   specified as a lexical variable, remove the ZEND_ACC_STATIC flag

   from the function flags and return immediately (and remove the

   current errormessage)

 - remove the T_STATIC from the grammar definition in zend_lang*.y



Unified diff of that should be max. 100 lines long.



So, this is NOT a limitation on the C level, this is a deliberate

design decision. And, btw., it is not a design decision I care about

very much - if there's a majority to change it, I've no problem with

that.



 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.



No, we did not do any such thing. People who do a lot of Javascript

expect the behaviour you describe (i.e. re-binding), but that does

not necessarily mean everybody does. And if you read postings made by

beginners with Javascript in beginners' web forums or beginners'

mailing lists, the re-binding of the this variable is a VERY confusing

thing for beginners and not natural at all. You may have grown

accustomed to this behaviour, but please do not make the mistake of

thinking that your expectations are the expectations of the rest of

the world. I do acknowledge that some people like you will expect

this behaviour due to their background in Javscript.



I also posted in HUGE DETAIL why I find your approach to be *very*

problematic. I also went into detail on why you find your approach

more natural and why Javascript is different than PHP in this aspect

so you can't simply copy the concept from one to another. I also

added a proposal which contains an alternative that may not be ideal

but may satisfy all the needs. But instead of really replying to

that, you simply took the first sentence, used my admittedly not

very ideal wording as polemic and repeated your statement from

before. I don't think this will get us anywhere.



So, I would be very happy if you could 1) acknowledge that what you

would expect is not necessarily that what everybody else would

expect (some others certainly, but not everybody), 2) realize that

many (albeit not all) things in the current implementation are NOT

there because of C limitations but are deliberate (see above for an

example) and 3) have another look at my previous posting, think

about it for some time and THEN reply to it. Because the intention

behind my posting was NOT to say you're wrong, you ... but rather

to say I get where you are coming from but have a look at this

example, your proposal will cause additional problems. And your

expectations do not necessarily match mine. But I don't want to

dismiss your idea completely, so here's an alternative idea that

came to my mind, please think about it.



Regards,

Christian



PS: By the way, Python does not rebind closures that enclose the

current object handle either:



class Foo:

  def __init__ (self, v):

self.v = v



  def getClosure (self):

def closure (w):

  return self.v + w

return closure



o1 = Foo (2)

o2 = Foo (3)

# both are o1.getClosure not o2!

o1.xyz = o1.getClosure()

o2.xyz = o1.getClosure()

print o1.xyz (2)   # 4

print o2.xyz (2)   # 4



(Yes, that's due to the different concept of the 'self' variable

in Python compared to the way PHP and Javascript use $this, but it

just demonstrates that one has to look at the other concepts that

are implemented in the language in order to get something

consistent. That's precisely my argument for PHP, too.)




-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: 

Re: [PHP-DEV] [RFC] prototyping

2009-01-18 Thread Christian Seiler
Hi Marcus,

 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.

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 

Re: [PHP-DEV] [RFC] prototyping

2009-01-17 Thread Marcus Boerger
Hello Stanislav,

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

 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.

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


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



Re: [PHP-DEV] [RFC] prototyping

2009-01-16 Thread Lukas Kahwe Smith

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

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



Re: [PHP-DEV] [RFC] prototyping

2009-01-15 Thread Lukas Kahwe Smith

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

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



Re: [PHP-DEV] [RFC] prototyping

2009-01-15 Thread Giovanni Giacobbi
On Thu, Jan 15, 2009 at 10:56:01AM +0100, Lukas Kahwe Smith wrote:
 
 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

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



Re: [PHP-DEV] [RFC] prototyping

2009-01-15 Thread David Zülke

Am 13.01.2009 um 22:58 schrieb Marcus Boerger:


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.


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

smime.p7s
Description: S/MIME cryptographic signature


Re: [PHP-DEV] [RFC] prototyping

2009-01-14 Thread Ionut Gabriel Stan



On 1/14/2009 01:15, Stanislav Malyshev wrote:

Hi!


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.


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.


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.





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 

Re: [PHP-DEV] [RFC] prototyping

2009-01-14 Thread Ionut Gabriel Stan

Hi,

On 1/14/2009 18:29, Stanislav Malyshev wrote:

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.
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


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



Re: [PHP-DEV] [RFC] prototyping

2009-01-14 Thread Stanislav Malyshev

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
s...@zend.com   http://www.zend.com/
(408)253-8829   MSN: s...@zend.com

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



Re: [PHP-DEV] [RFC] prototyping

2009-01-13 Thread Etienne Kneuss
Hello,

On Tue, Jan 13, 2009 at 12:07 AM, Stanislav Malyshev s...@zend.com wrote:
 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.

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
 s...@zend.com   http://www.zend.com/
 (408)253-8829   MSN: s...@zend.com

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







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

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

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



Re: [PHP-DEV] [RFC] prototyping

2009-01-13 Thread Marcus Boerger
Hello Stanislav,

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

 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.

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.

 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?

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.

 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.

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.

 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?

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.

 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.

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


-- 
PHP Internals - PHP Runtime Development Mailing List
To 

Re: [PHP-DEV] [RFC] prototyping

2009-01-13 Thread Stanislav Malyshev

Hi!

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.


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
s...@zend.com   http://www.zend.com/
(408)253-8829   MSN: s...@zend.com

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



Re: [PHP-DEV] [RFC] prototyping

2009-01-13 Thread Xuefer
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.

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



Re: [PHP-DEV] [RFC] prototyping

2009-01-12 Thread Stanislav Malyshev

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
s...@zend.com   http://www.zend.com/
(408)253-8829   MSN: s...@zend.com

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