Re: [PHP-DEV] Object Casting - An Alternative to Type Hinting
On Tue, Feb 28, 2012 at 6:05 AM, Anthony Ferrara ircmax...@gmail.comwrote: Ok, I've made a proof-of-concept patch here: https://gist.github.com/1929587 Note that there are still a few memory leaks in there that would need to be cleaned up, but I just wanted to make a really quick POC before cleaning anything up to make it worthy of addition... One could use zend_get_type_by_const() for help :) Another patch would need to be made for the __castFrom($value) implementation, but I think we'll split that off into another topic/RFC since that's quite a bit more work than this is... What are your thoughts? Anyway... I like but the changes would really need some documentation. And before that, we would need several RFC (one per concept seems to be a good idea). It adds 2 new magic methods: __castTo($type) and __assign($value): __castTo($type) is called by the cast_object handler, and the get handler. The cast_object handler will pass in the requested type as a string (NULL, boolean, integer, double, string, array, object, resource, callable). Note that it does not check the return type (yet at least). The get handler will pass in native as $type. So that's used by combination operators (+=, +=, etc). __assign($value) is called by the set handler. This gets called anytime the object is assigned to. To allow for conditional assignment, if you return false from the handler, the value overwrites the zval (to allow for destructing of the object and not overriding assignment, if you want)... So, with this script: ?php class Foo { public $value = 1; } class Bar { public $value = 1; public function __castTo($type) { return $this-value; } public function __assign($value) { $this-value = $value; return $value != 10; } } $a = new Foo; $b = new Bar; $a++; var_dump($a); // int(1) - Normal type casting rules apply here. $b++; var_dump($b); // object, value = 2, increment captured $a = new Foo; $b = new Bar; $a = 3; $b = 3; var_dump($a); // int(3) - Normal rules apply var_dump($b); // object, value = 3, assignment captured $a = new Foo; $b = new Bar; $a = 10; $b = 10; var_dump($a); // int(10) - Normal rules apply var_dump($b); // int(10) - False was returned, so normal assignment happens Now, for some casting: $a = new Foo; $b = new Bar; $a-value = 100; $b-value = 100; var_dump((int) $a); // int(1) - Normal type casting rules apply var_dump((int) $b); // int(100) - Cast was captured $a = new Foo; $b = new Bar; $a-value = 2; $b-value = 2; var_dump(substr(test, $a)); // string(1) t var_dump(substr(test, $b)); // string(1) te Anthony Sorry for repeating, but why not RFC that ? Julien.P On Mon, Feb 27, 2012 at 3:24 PM, Anthony Ferrara ircmax...@gmail.com wrote: Rich, I appreciate the candid and honest nature of your reply, while maintaining civility. This list needs more of that. Further replies inline: On Mon, Feb 27, 2012 at 1:54 PM, Richard Lynch c...@l-i-e.com wrote: On Mon, February 27, 2012 9:20 am, Anthony Ferrara wrote: I have to say that no matter how much a luv my OOP, turning every built-in type into an Object is just a Bad Idea... It's a form of bloat on RAM and CPU with minimal added value, imho. Re-read what I had written. I never said to turn every built-in type into an object. In fact, what I was talking about was keeping and preserving the base types as-is. All that I was proposing was adding the ability to cast from and to the primitives. That way you could silently convert back and forth as needed (transparently when possible). I apologize that my brevity has been misconstrued. You are certainly free, even with the tools available in PHP, to wrap an object around integers, strings, and so on. There may even be occasions where I think that would be a Good Idea (tm). Well, you can kind of do it now. You can't directly operate on those objects. You need to first manually cast them back to the native type. Take a look at SplFixedArray ( http://www.php.net/manual/en/class.splfixedarray.php ). It has a pair of methods, a static fromArray(), and a instance toArray(). What I'm talking about is adding the ability to push these conversions down to the engine level. What I object to is building such a facility into core PHP, because: 1) You can already do it in userland, and I believe that's where it belongs. Actually, almost exactly the opposite. You can't do it in userland, but you can in a PECL extension (via cast_object(), get() and set()). The first part of this proposal is basically just exposing those methods (almost 1:1, only consolidating cast_object and get into a single method with a parameter defining the difference). 2) It unnecessarily [see 1] complicates core PHP, whose major strengths that drive its success includes its simplicity. Actually, the first part
Re: [PHP-DEV] Object Casting - An Alternative to Type Hinting
One could use zend_get_type_by_const() for help :) I wasn't aware of that function, thanks! I based it off of gettype ( http://lxr.php.net/opengrok/xref/PHP_5_4/ext/standard/type.c#26 ). I'll update the patch tonight. And before that, we would need several RFC (one per concept seems to be a good idea). Well, considering they are tied together (at least __assign is useless without the __castTo), wouldn't the two of them fall into the same RFC? And I'm planning on writing out an RFC for it. I just wanted to get some comments and flush out the concept before writing an official patch and RFC. That's why I made a POC patch, to investigate the ramifications and prove it could be done before finalizing and proposing exactly how it should work... Thanks, Anthony On Tue, Feb 28, 2012 at 5:54 AM, jpauli jpa...@php.net wrote: On Tue, Feb 28, 2012 at 6:05 AM, Anthony Ferrara ircmax...@gmail.com wrote: Ok, I've made a proof-of-concept patch here: https://gist.github.com/1929587 Note that there are still a few memory leaks in there that would need to be cleaned up, but I just wanted to make a really quick POC before cleaning anything up to make it worthy of addition... One could use zend_get_type_by_const() for help :) Another patch would need to be made for the __castFrom($value) implementation, but I think we'll split that off into another topic/RFC since that's quite a bit more work than this is... What are your thoughts? Anyway... I like but the changes would really need some documentation. And before that, we would need several RFC (one per concept seems to be a good idea). It adds 2 new magic methods: __castTo($type) and __assign($value): __castTo($type) is called by the cast_object handler, and the get handler. The cast_object handler will pass in the requested type as a string (NULL, boolean, integer, double, string, array, object, resource, callable). Note that it does not check the return type (yet at least). The get handler will pass in native as $type. So that's used by combination operators (+=, +=, etc). __assign($value) is called by the set handler. This gets called anytime the object is assigned to. To allow for conditional assignment, if you return false from the handler, the value overwrites the zval (to allow for destructing of the object and not overriding assignment, if you want)... So, with this script: ?php class Foo { public $value = 1; } class Bar { public $value = 1; public function __castTo($type) { return $this-value; } public function __assign($value) { $this-value = $value; return $value != 10; } } $a = new Foo; $b = new Bar; $a++; var_dump($a); // int(1) - Normal type casting rules apply here. $b++; var_dump($b); // object, value = 2, increment captured $a = new Foo; $b = new Bar; $a = 3; $b = 3; var_dump($a); // int(3) - Normal rules apply var_dump($b); // object, value = 3, assignment captured $a = new Foo; $b = new Bar; $a = 10; $b = 10; var_dump($a); // int(10) - Normal rules apply var_dump($b); // int(10) - False was returned, so normal assignment happens Now, for some casting: $a = new Foo; $b = new Bar; $a-value = 100; $b-value = 100; var_dump((int) $a); // int(1) - Normal type casting rules apply var_dump((int) $b); // int(100) - Cast was captured $a = new Foo; $b = new Bar; $a-value = 2; $b-value = 2; var_dump(substr(test, $a)); // string(1) t var_dump(substr(test, $b)); // string(1) te Anthony Sorry for repeating, but why not RFC that ? Julien.P On Mon, Feb 27, 2012 at 3:24 PM, Anthony Ferrara ircmax...@gmail.com wrote: Rich, I appreciate the candid and honest nature of your reply, while maintaining civility. This list needs more of that. Further replies inline: On Mon, Feb 27, 2012 at 1:54 PM, Richard Lynch c...@l-i-e.com wrote: On Mon, February 27, 2012 9:20 am, Anthony Ferrara wrote: I have to say that no matter how much a luv my OOP, turning every built-in type into an Object is just a Bad Idea... It's a form of bloat on RAM and CPU with minimal added value, imho. Re-read what I had written. I never said to turn every built-in type into an object. In fact, what I was talking about was keeping and preserving the base types as-is. All that I was proposing was adding the ability to cast from and to the primitives. That way you could silently convert back and forth as needed (transparently when possible). I apologize that my brevity has been misconstrued. You are certainly free, even with the tools available in PHP, to wrap an object around integers, strings, and so on. There may even be occasions where I think that would be a Good Idea (tm). Well, you can kind of do it now. You can't directly operate on those objects. You need to first manually cast them back to the native type. Take a look at SplFixedArray (
Re: [PHP-DEV] Object Casting - An Alternative to Type Hinting
On Mon, February 27, 2012 11:05 pm, Anthony Ferrara wrote: ?php class Foo { public $value = 1; } class Bar { public $value = 1; public function __castTo($type) { return $this-value; } public function __assign($value) { $this-value = $value; return $value != 10; } } $a = new Foo; $b = new Bar; $a++; So, here's the thing... This obviously trivial example makes perfect sense, until you realize that some moron (and PHP has lots of them) will sooner or later make ++ do something completely weird, and I'm going to have to edit their code-base and will have to dig through umpteen class files to figure out what the heck ++ means... I can see a lot of legitimate serious coders using this wisely. Unfortunately, I can see a million scripters using it very un-wisely. I can even see people overloading the plus operator for an object wrapped around an array in multiple different ways, then pulling in different libraries that seem quite useful, and the only way I can figure out what + means is to dig through even more files and figure out which bastard child this object comes from, that was passed into some random function that uses + on it. And then god knows what happens when you do: $foo = new Foo(); //from library A $bar = new Bar(); //from library B $foobar = $foo + $bar; //Will this last statement even make sense, even though both Foo and Bar override the + operator, just in entirely different ways... How can you even guarantee that $foo, presumably taking precedence, won't attempt to access a non-existent property of Bar, generating an ignored E_NOTICE on most hosts, and introduce a subtle bug that nobody notices for months, even years, in a seldom-used function? Consider the trivial example where Foo uses array_sum() and Bar uses count() comes up with a number. It's a totally meaningless number in any real-world scenario. How would one detect this bug, really, in some mish-mash of libraries from PEAR/PECL/homebrew-MVC/Framework. I'm sure you can define the rules in a page or so for precedence in type-casting and what happens when. But I really am not interested in figuring out the rules for + when I've been using it the same way since 2nd grade, with modest changes over the years that follow the spirit of + Your proposal lets one re-define + to mean whatever one wants, and while you might not abuse that, somebody else will... You might as well install runkit on everybody's server and let them have at it. :-) PHP was founded on the KISS principle, so that newbies can, in fact, write sub-optimal but working code quickly to get a website up, and to keep newbie fingers out of mashing gears. This is way over-the-top from that principle. -- brain cancer update: http://richardlynch.blogspot.com/search/label/brain%20tumor Donate: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclickhosted_button_id=FS9NLTNEEKWBE -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] Object Casting - An Alternative to Type Hinting
Richard, This is not overloading addition. Not by a long shot. This is overloading casting to primitives (which happens in the case of addition, but a bunch of others). It turns out that the addition operator calls object-get in C to get the primitive value of the object if it exists. That's where this works. So: This obviously trivial example makes perfect sense, until you realize that some moron (and PHP has lots of them) will sooner or later make ++ do something completely weird, and I'm going to have to edit their code-base and will have to dig through umpteen class files to figure out what the heck ++ means... Yes, the example is trivial. And yes, it can be abused. But I think you're blowing it WAY out of proportion. ++ still means what it always has meant. It's the *exact* same as normal (addition is still happening). The only change is where the addition gets its value, and where that value is stored. And it's not really digging through umpteen classes to figure out what the cast is. To be honest, you could say the exact same thing about polymorphism. And the indirection there is actually seen as a *good* thing. So I'm not sure what argument you're trying to make aside from that you don't like it... And then god knows what happens when you do: $foo = new Foo(); //from library A $bar = new Bar(); //from library B $foobar = $foo + $bar; //Will this last statement even make sense, even though both Foo and Bar override the + operator, just in entirely different ways... Neither override anything. let me say this again: THIS IS NOT DOING OPERATOR OVERLOADING. That's 100% predictable. Lookup Foo and Bar, and see if either/both implement __castTo. If so, the types they return will tell you exactly what it will be. How can you even guarantee that $foo, presumably taking precedence, won't attempt to access a non-existent property of Bar, generating an ignored E_NOTICE on most hosts, and introduce a subtle bug that nobody notices for months, even years, in a seldom-used function? You don't need to. Because $foo will never know about $bar (or vise versa)... And to be honest, you could say the same thing about LOTS of existing NON-MAGIC functionality. So I don't see that this contributes to the conversation at all... Your proposal lets one re-define + to mean whatever one wants, and while you might not abuse that, somebody else will... Ok, This is rediculous. Open the patch. Tell me where it redefines +, or even remotely can be used to... + is still a scalar operator, and with this patch you cannot change that. The only thing this patch lets you do with respect to the + operator is choose what the scalar representation of the object is... Personal Note: I appreciate replies and concerns. But at least read the patch and try to understand what the POC does before going off on a rant that does nothing but turn people off unless you actually realize what's going on. If you don't understand what it does, then ask. But don't complain about things the feature doesn't even touch, it's disrespectful and doesn't accomplish anything but to add noise to the conversation. Anthony On Tue, Feb 28, 2012 at 4:37 PM, Richard Lynch c...@l-i-e.com wrote: On Mon, February 27, 2012 11:05 pm, Anthony Ferrara wrote: ?php class Foo { public $value = 1; } class Bar { public $value = 1; public function __castTo($type) { return $this-value; } public function __assign($value) { $this-value = $value; return $value != 10; } } $a = new Foo; $b = new Bar; $a++; So, here's the thing... This obviously trivial example makes perfect sense, until you realize that some moron (and PHP has lots of them) will sooner or later make ++ do something completely weird, and I'm going to have to edit their code-base and will have to dig through umpteen class files to figure out what the heck ++ means... I can see a lot of legitimate serious coders using this wisely. Unfortunately, I can see a million scripters using it very un-wisely. I can even see people overloading the plus operator for an object wrapped around an array in multiple different ways, then pulling in different libraries that seem quite useful, and the only way I can figure out what + means is to dig through even more files and figure out which bastard child this object comes from, that was passed into some random function that uses + on it. And then god knows what happens when you do: $foo = new Foo(); //from library A $bar = new Bar(); //from library B $foobar = $foo + $bar; //Will this last statement even make sense, even though both Foo and Bar override the + operator, just in entirely different ways... How can you even guarantee that $foo, presumably taking precedence, won't attempt to access a non-existent property of Bar, generating an ignored E_NOTICE on most hosts, and introduce a subtle bug that nobody notices for months, even
Re: [PHP-DEV] Object Casting - An Alternative to Type Hinting
I think this is +1 for moving the conversation to a less crowded location. Sorry guys I know I keep promising to take care of it but I've been swamped all day. I'll try to find some time though. --Kris On Tue, Feb 28, 2012 at 4:28 PM, Anthony Ferrara ircmax...@gmail.comwrote: Richard, This is not overloading addition. Not by a long shot. This is overloading casting to primitives (which happens in the case of addition, but a bunch of others). It turns out that the addition operator calls object-get in C to get the primitive value of the object if it exists. That's where this works. So: This obviously trivial example makes perfect sense, until you realize that some moron (and PHP has lots of them) will sooner or later make ++ do something completely weird, and I'm going to have to edit their code-base and will have to dig through umpteen class files to figure out what the heck ++ means... Yes, the example is trivial. And yes, it can be abused. But I think you're blowing it WAY out of proportion. ++ still means what it always has meant. It's the *exact* same as normal (addition is still happening). The only change is where the addition gets its value, and where that value is stored. And it's not really digging through umpteen classes to figure out what the cast is. To be honest, you could say the exact same thing about polymorphism. And the indirection there is actually seen as a *good* thing. So I'm not sure what argument you're trying to make aside from that you don't like it... And then god knows what happens when you do: $foo = new Foo(); //from library A $bar = new Bar(); //from library B $foobar = $foo + $bar; //Will this last statement even make sense, even though both Foo and Bar override the + operator, just in entirely different ways... Neither override anything. let me say this again: THIS IS NOT DOING OPERATOR OVERLOADING. That's 100% predictable. Lookup Foo and Bar, and see if either/both implement __castTo. If so, the types they return will tell you exactly what it will be. How can you even guarantee that $foo, presumably taking precedence, won't attempt to access a non-existent property of Bar, generating an ignored E_NOTICE on most hosts, and introduce a subtle bug that nobody notices for months, even years, in a seldom-used function? You don't need to. Because $foo will never know about $bar (or vise versa)... And to be honest, you could say the same thing about LOTS of existing NON-MAGIC functionality. So I don't see that this contributes to the conversation at all... Your proposal lets one re-define + to mean whatever one wants, and while you might not abuse that, somebody else will... Ok, This is rediculous. Open the patch. Tell me where it redefines +, or even remotely can be used to... + is still a scalar operator, and with this patch you cannot change that. The only thing this patch lets you do with respect to the + operator is choose what the scalar representation of the object is... Personal Note: I appreciate replies and concerns. But at least read the patch and try to understand what the POC does before going off on a rant that does nothing but turn people off unless you actually realize what's going on. If you don't understand what it does, then ask. But don't complain about things the feature doesn't even touch, it's disrespectful and doesn't accomplish anything but to add noise to the conversation. Anthony On Tue, Feb 28, 2012 at 4:37 PM, Richard Lynch c...@l-i-e.com wrote: On Mon, February 27, 2012 11:05 pm, Anthony Ferrara wrote: ?php class Foo { public $value = 1; } class Bar { public $value = 1; public function __castTo($type) { return $this-value; } public function __assign($value) { $this-value = $value; return $value != 10; } } $a = new Foo; $b = new Bar; $a++; So, here's the thing... This obviously trivial example makes perfect sense, until you realize that some moron (and PHP has lots of them) will sooner or later make ++ do something completely weird, and I'm going to have to edit their code-base and will have to dig through umpteen class files to figure out what the heck ++ means... I can see a lot of legitimate serious coders using this wisely. Unfortunately, I can see a million scripters using it very un-wisely. I can even see people overloading the plus operator for an object wrapped around an array in multiple different ways, then pulling in different libraries that seem quite useful, and the only way I can figure out what + means is to dig through even more files and figure out which bastard child this object comes from, that was passed into some random function that uses + on it. And then god knows what happens when you do: $foo = new Foo(); //from library A $bar = new Bar(); //from library B $foobar =
Re: [PHP-DEV] Object Casting - An Alternative to Type Hinting
On Sun, February 26, 2012 9:48 am, Anthony Ferrara wrote: I have to say that no matter how much a luv my OOP, turning every built-in type into an Object is just a Bad Idea... It's a form of bloat on RAM and CPU with minimal added value, imho. No matter which way you twist this pretzel: -1 -- brain cancer update: http://richardlynch.blogspot.com/search/label/brain%20tumor Donate: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclickhosted_button_id=FS9NLTNEEKWBE -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] Object Casting - An Alternative to Type Hinting
On Sun, February 26, 2012 8:45 pm, Anthony Ferrara wrote: Or operator-overlading to the rescue? :-) Not quite. Especially because with operator overloading done at this level (how it would be implemented in PHP) it's almost impossible to make it consistent: class string { public function overload+($mixed) { return $this-value + $mixed; I think you meant '.' here instead of '+' Otherwise, PHP type juggling will make it be 10 as well. } } class Integer { public function overload+($mixed) { return $this-value + $mixed; } } $int = new Integer(5); $string = new String(5); echo $int + $string; // 10 echo $string + $int; // 55 While I like the concept of overloading, I don't really think it's solvable in a consistent enough manner that it would work here. That said, there is no inconsistency. If what you want to do is overload + on strings to do concatenation, then it's on you to typecast everything to (string) for it to make sense. Oh, and string is a reserved word, so this won't work as-is, though that's obviously picuyane. -- brain cancer update: http://richardlynch.blogspot.com/search/label/brain%20tumor Donate: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclickhosted_button_id=FS9NLTNEEKWBE -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] Object Casting - An Alternative to Type Hinting
I have to say that no matter how much a luv my OOP, turning every built-in type into an Object is just a Bad Idea... It's a form of bloat on RAM and CPU with minimal added value, imho. No matter which way you twist this pretzel: -1 Re-read what I had written. I never said to turn every built-in type into an object. In fact, what I was talking about was keeping and preserving the base types as-is. All that I was proposing was adding the ability to cast from and to the primitives. That way you could silently convert back and forth as needed (transparently when possible). So what it sounds like you're -1ing to, is not actually what was proposed... I'm starting to work on a patch for this as a proof of concept... Anthony On Mon, Feb 27, 2012 at 10:08 AM, Richard Lynch c...@l-i-e.com wrote: On Sun, February 26, 2012 9:48 am, Anthony Ferrara wrote: I have to say that no matter how much a luv my OOP, turning every built-in type into an Object is just a Bad Idea... It's a form of bloat on RAM and CPU with minimal added value, imho. No matter which way you twist this pretzel: -1 -- brain cancer update: http://richardlynch.blogspot.com/search/label/brain%20tumor Donate: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclickhosted_button_id=FS9NLTNEEKWBE -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] Object Casting - An Alternative to Type Hinting
On 27/02/12 16:12, Richard Lynch wrote: Oh, and string is a reserved word, so this won't work as-is, though that's obviously picuyane. It's not, you can perfectly define your own class called 'string'. I'd be much easier if it were, though. -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] Object Casting - An Alternative to Type Hinting
On Mon, February 27, 2012 9:20 am, Anthony Ferrara wrote: I have to say that no matter how much a luv my OOP, turning every built-in type into an Object is just a Bad Idea... It's a form of bloat on RAM and CPU with minimal added value, imho. Re-read what I had written. I never said to turn every built-in type into an object. In fact, what I was talking about was keeping and preserving the base types as-is. All that I was proposing was adding the ability to cast from and to the primitives. That way you could silently convert back and forth as needed (transparently when possible). I apologize that my brevity has been misconstrued. You are certainly free, even with the tools available in PHP, to wrap an object around integers, strings, and so on. There may even be occasions where I think that would be a Good Idea (tm). What I object to is building such a facility into core PHP, because: 1) You can already do it in userland, and I believe that's where it belongs. 2) It unnecessarily [see 1] complicates core PHP, whose major strengths that drive its success includes its simplicity. No matter which way you twist this pretzel: I had hoped that this bit would hint that all the proposals along these lines, including yours, are proposals I would vote against, even though I did over-blow your actual proposal. -1 So what it sounds like you're -1ing to, is not actually what was proposed... I'm starting to work on a patch for this as a proof of concept... Please do so! I'll still vote -1, but obviously others will vote as they see fit. All these ideas are welcome. The ones with complete patches even more so, as they allow a true idea of what the change would mean. Unfortunately, however, I must repeat that, so far, the idea has always fallen flat on its face when the proposer actually attempts to put action into deed, making a patch that fully meets their proposal. That doesn't mean you can't succeed, if you are more skilled than all your predecessors. -- brain cancer update: http://richardlynch.blogspot.com/search/label/brain%20tumor Donate: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclickhosted_button_id=FS9NLTNEEKWBE -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] Object Casting - An Alternative to Type Hinting
On 2012-02-27, Richard Lynch c...@l-i-e.com wrote: On Mon, February 27, 2012 9:20 am, Anthony Ferrara wrote: I have to say that no matter how much a luv my OOP, turning every built-in type into an Object is just a Bad Idea... It's a form of bloat on RAM and CPU with minimal added value, imho. Re-read what I had written. I never said to turn every built-in type into an object. In fact, what I was talking about was keeping and preserving the base types as-is. All that I was proposing was adding the ability to cast from and to the primitives. That way you could silently convert back and forth as needed (transparently when possible). I apologize that my brevity has been misconstrued. You are certainly free, even with the tools available in PHP, to wrap an object around integers, strings, and so on. There may even be occasions where I think that would be a Good Idea (tm). What I object to is building such a facility into core PHP, because: 1) You can already do it in userland, and I believe that's where it belongs. Actually, you can't. The point of Anthony's proposal is that while we _can_ wrap scalar types in objects, that fails for the instances where you need to perform operations with them. This is why he's proposing the ability to cast to and from these scalar objects, and have calls in the engine that would do the casting on-demand. 2) It unnecessarily [see 1] complicates core PHP, whose major strengths that drive its success includes its simplicity. The flip-side of the argument is that if many developers are doing code like this over and over again: public function setNumber($number) { if (!is_scalar($number)) { throw new InvalidArgumentException('Need a number!'); } $this-number = (int) $number; } ... then it may be time for the language to make this easier. (And just because _you_ or a subset of developers on internals don't write code this way does not mean a _majority_ of developers do not.) -- Matthew Weier O'Phinney Project Lead| matt...@zend.com Zend Framework | http://framework.zend.com/ PGP key: http://framework.zend.com/zf-matthew-pgp-key.asc -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] Object Casting - An Alternative to Type Hinting
Rich, I appreciate the candid and honest nature of your reply, while maintaining civility. This list needs more of that. Further replies inline: On Mon, Feb 27, 2012 at 1:54 PM, Richard Lynch c...@l-i-e.com wrote: On Mon, February 27, 2012 9:20 am, Anthony Ferrara wrote: I have to say that no matter how much a luv my OOP, turning every built-in type into an Object is just a Bad Idea... It's a form of bloat on RAM and CPU with minimal added value, imho. Re-read what I had written. I never said to turn every built-in type into an object. In fact, what I was talking about was keeping and preserving the base types as-is. All that I was proposing was adding the ability to cast from and to the primitives. That way you could silently convert back and forth as needed (transparently when possible). I apologize that my brevity has been misconstrued. You are certainly free, even with the tools available in PHP, to wrap an object around integers, strings, and so on. There may even be occasions where I think that would be a Good Idea (tm). Well, you can kind of do it now. You can't directly operate on those objects. You need to first manually cast them back to the native type. Take a look at SplFixedArray ( http://www.php.net/manual/en/class.splfixedarray.php ). It has a pair of methods, a static fromArray(), and a instance toArray(). What I'm talking about is adding the ability to push these conversions down to the engine level. What I object to is building such a facility into core PHP, because: 1) You can already do it in userland, and I believe that's where it belongs. Actually, almost exactly the opposite. You can't do it in userland, but you can in a PECL extension (via cast_object(), get() and set()). The first part of this proposal is basically just exposing those methods (almost 1:1, only consolidating cast_object and get into a single method with a parameter defining the difference). 2) It unnecessarily [see 1] complicates core PHP, whose major strengths that drive its success includes its simplicity. Actually, the first part of the proposal doesn't really change the core that much. All it does is add standard object handlers to expose cast_object (which is already partially exposed via __toString), get and set (which are currently null). There shouldn't really be other changes required to the core for the first part at least. The second part of the proposal (the castFrom auto-casting) would require some more changes to the core, and be much more significant. To be honest, I think that would be a separate effort (and a separate RFC) the more I think about it. No matter which way you twist this pretzel: I had hoped that this bit would hint that all the proposals along these lines, including yours, are proposals I would vote against, even though I did over-blow your actual proposal. -1 So what it sounds like you're -1ing to, is not actually what was proposed... I'm starting to work on a patch for this as a proof of concept... Please do so! I'll still vote -1, but obviously others will vote as they see fit. All these ideas are welcome. The ones with complete patches even more so, as they allow a true idea of what the change would mean. Unfortunately, however, I must repeat that, so far, the idea has always fallen flat on its face when the proposer actually attempts to put action into deed, making a patch that fully meets their proposal. That doesn't mean you can't succeed, if you are more skilled than all your predecessors. I don't think skill has that much to do with it. I think the real key difference is what's being attempted... Anthony -- brain cancer update: http://richardlynch.blogspot.com/search/label/brain%20tumor Donate: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclickhosted_button_id=FS9NLTNEEKWBE -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] Object Casting - An Alternative to Type Hinting
Ok, I've made a proof-of-concept patch here: https://gist.github.com/1929587 Note that there are still a few memory leaks in there that would need to be cleaned up, but I just wanted to make a really quick POC before cleaning anything up to make it worthy of addition... Another patch would need to be made for the __castFrom($value) implementation, but I think we'll split that off into another topic/RFC since that's quite a bit more work than this is... What are your thoughts? It adds 2 new magic methods: __castTo($type) and __assign($value): __castTo($type) is called by the cast_object handler, and the get handler. The cast_object handler will pass in the requested type as a string (NULL, boolean, integer, double, string, array, object, resource, callable). Note that it does not check the return type (yet at least). The get handler will pass in native as $type. So that's used by combination operators (+=, +=, etc). __assign($value) is called by the set handler. This gets called anytime the object is assigned to. To allow for conditional assignment, if you return false from the handler, the value overwrites the zval (to allow for destructing of the object and not overriding assignment, if you want)... So, with this script: ?php class Foo { public $value = 1; } class Bar { public $value = 1; public function __castTo($type) { return $this-value; } public function __assign($value) { $this-value = $value; return $value != 10; } } $a = new Foo; $b = new Bar; $a++; var_dump($a); // int(1) - Normal type casting rules apply here. $b++; var_dump($b); // object, value = 2, increment captured $a = new Foo; $b = new Bar; $a = 3; $b = 3; var_dump($a); // int(3) - Normal rules apply var_dump($b); // object, value = 3, assignment captured $a = new Foo; $b = new Bar; $a = 10; $b = 10; var_dump($a); // int(10) - Normal rules apply var_dump($b); // int(10) - False was returned, so normal assignment happens Now, for some casting: $a = new Foo; $b = new Bar; $a-value = 100; $b-value = 100; var_dump((int) $a); // int(1) - Normal type casting rules apply var_dump((int) $b); // int(100) - Cast was captured $a = new Foo; $b = new Bar; $a-value = 2; $b-value = 2; var_dump(substr(test, $a)); // string(1) t var_dump(substr(test, $b)); // string(1) te Anthony On Mon, Feb 27, 2012 at 3:24 PM, Anthony Ferrara ircmax...@gmail.com wrote: Rich, I appreciate the candid and honest nature of your reply, while maintaining civility. This list needs more of that. Further replies inline: On Mon, Feb 27, 2012 at 1:54 PM, Richard Lynch c...@l-i-e.com wrote: On Mon, February 27, 2012 9:20 am, Anthony Ferrara wrote: I have to say that no matter how much a luv my OOP, turning every built-in type into an Object is just a Bad Idea... It's a form of bloat on RAM and CPU with minimal added value, imho. Re-read what I had written. I never said to turn every built-in type into an object. In fact, what I was talking about was keeping and preserving the base types as-is. All that I was proposing was adding the ability to cast from and to the primitives. That way you could silently convert back and forth as needed (transparently when possible). I apologize that my brevity has been misconstrued. You are certainly free, even with the tools available in PHP, to wrap an object around integers, strings, and so on. There may even be occasions where I think that would be a Good Idea (tm). Well, you can kind of do it now. You can't directly operate on those objects. You need to first manually cast them back to the native type. Take a look at SplFixedArray ( http://www.php.net/manual/en/class.splfixedarray.php ). It has a pair of methods, a static fromArray(), and a instance toArray(). What I'm talking about is adding the ability to push these conversions down to the engine level. What I object to is building such a facility into core PHP, because: 1) You can already do it in userland, and I believe that's where it belongs. Actually, almost exactly the opposite. You can't do it in userland, but you can in a PECL extension (via cast_object(), get() and set()). The first part of this proposal is basically just exposing those methods (almost 1:1, only consolidating cast_object and get into a single method with a parameter defining the difference). 2) It unnecessarily [see 1] complicates core PHP, whose major strengths that drive its success includes its simplicity. Actually, the first part of the proposal doesn't really change the core that much. All it does is add standard object handlers to expose cast_object (which is already partially exposed via __toString), get and set (which are currently null). There shouldn't really be other changes required to the core for the first part at least. The second part of the proposal (the castFrom auto-casting) would require some more changes to the core, and be much more significant. To be
RE: [PHP-DEV] Object Casting - An Alternative to Type Hinting
I definitely like the idea of being able to cast objects, I've frequently wished to be able to cast an object to an array. I would argue against the single __castTo() and __castFrom() magic methods as large switches get to be difficult to find/read and doesn't support separation. I would prefer something along the lines of C++ such as: Cast From: public __construct(Integer $i); Cast To: public Integer(); This would require function overloading (__construct overloading by type) but with Type Hinting already available for function parameters, this could be done relatively easily I think. Doing this would keep code isolated with smaller functions. -Clint -Original Message- From: Anthony Ferrara [mailto:ircmax...@gmail.com] Sent: Sunday, February 26, 2012 8:57 AM To: internals@lists.php.net Subject: [PHP-DEV] Object Casting - An Alternative to Type Hinting I've gone back and re-read a bunch of the old posts on Type Hinting, and have come to the conclusion that it won't be done any time soon. Not because it doesn't have merit, but because there are at least a few fundamental difficulties that are non-trivial to figure out while still keeping the usefulness. So, I started thinking of a way that we can work around it. One technique that has been passed around is to use object wrappers and pass objects instead of scalars. Such as was suggested in: http://marc.info/?l=php-internalsm=119543188808737w=2 One of the problems associated with this, is that before you work with these types, you need to manually cast them back to the native type they represent. We can try to deal with this problem using __toString, but I don't think that's granular enough to really be of much use in solving this problem... Another method we could use, is if we supported operator overloading in objects. That way, we could overload the addition operator to handle the operation. However, this becomes quite problematic, since ordering of operations and interaction with disparate class trees is going to get rather messy (and extremely fragile) quite quick. Let me throw out another possible solution. What if we added two new magic methods to objects: public function __castTo($type); public static function __castFrom($value); With these two methods, we could enable type-hinting by using something very similar to auto-boxing. Let me start with a sample implementation: class Integer { protected $value = 0; public function __construct($value) { $this-value = $value; } public function __castTo($type) { switch ($type) { case 'int': case 'numeric': return $this-value; case 'float': return (float) $this-value; } throw new LogicException('Illegal Cast Operation Performed'); } public static function __castFrom($value) { if (!is_scalar($value)) { throw new LogicException('Illegal Cast Operation Performed'); } return new static((int) $value); } } Now, that enables us to do something like: $int = new Integer(2); echo $int + 2; // 4, since __castTo was called with numeric echo substr(foobar, 0, $int); // fo since __castTo was called with int That demonstrates the __castTo usages. Now for the __castFrom... function foo(Integer $int) { echo $int + 1; } Now, under current rules, calling foo(1) would result in a fatal error. However, we could change that to check if the class being type-hinted for has a __castFrom method on it. If it does, it would attempt to cast the value into that class. So calling foo(1) would actually internally call `Integer::__castFrom(1)`. And since that returns an object of instance Integer, the hint would pass. These two additions would solve a few issues with type-hinting. First off, it solves the cast to vs error if debate on passing a string in the place of an integer. In this case, it would be up to the __castFrom() method to determine that (thereby enabling both worlds possible). Second, it solves the problem of having to wrap clumsy APIs around scalars for hinting purposes ($foo-getInteger() + 1). Third, it is still completely optional... Fourth, it keeps and tries to embrace the dynamic type-cohersion nature of PHP... Now, that's not to say it's not without problems. Here are a few that I can think of: 1. How should it deal with references? If I do `function foo(Integer $int)`, what should happen? - I would argue that if you're trying to reference, the casting functionality should not be expected to work at all. But that introduces some inconsistency there. Not sure how to solve that... 2. Should it support casting from one object to another? Meaning if I pass an SPLInt to something expecting Integer (from two different trees), should __castFrom be called? - I would argue that yes, it should. That would open the door for compatibility layers to be built for
Re: [PHP-DEV] Object Casting - An Alternative to Type Hinting
Clint, First off, thanks for the reply. With respect to the large switches, that could easily be avoided with something like: public function __castTo($type) { $method = 'castTo' . $type; if (method_exists(array($this, $method))) { return $this-$method(); } throw new LogicException('Illegal Cast Attempted'); } That way, you could have a castToInt function, a castToFloat function, etc. It would be up to you though if you want to do that... With respect to the overloading, that's a different beast. Right now, to implement casting, the changes can be reasonably isolated to the parts of code that do the zval conversions, and the parts of code that enforce the type hints. That means that, while it's not a trivial patch by any means, it shouldn't break 3pd extensions as long as they are using the core functions. If we wanted to implement overloading, that's a HUGE change. Right now, functions/methods are looked up via a hash table based on name. So if we wanted to change that, we'd need to change it to a hash table by name, with a linked list of signatures. And given that the signature expansion would be non-trivial (order would be important, as you could type-hint on different parts of the tree), performance would be a concern. Not to mention that in order for it to work, it would also need to check not only if the arguments are the given types, but if they can be converted to the given types... So performance for each function call could go to absolute crap... Not to mention, all 3pd extensions would break since they are not passing signature information when looking up functions/methods to call. So it would be a major engine level change to implement, and hence not be possible until PHP6 (or 7, or 10, or whatever). Not to mention the point with the castFrom part where if you have a class as the same name of a method, it could inadvertantly try to cast it to that class (which is non-intentional). In this case, I'd much rather have a single magic method which would then be unambiguous and have minimal chance for accidental conflict with existing functionality (given that the __ prefix is documented as magic and can change at any time). Additionally, I purposely avoided using the constructor for the __castFrom() magic, since casting and instantiating are clearly two different tasks. The static function __castFrom() acts as a factory method, which then decouples the instantiation from the cast operation. In addition, it allows for different behavior when casting from scalars (different for each scalar type), which would not be possible with your constructor overloading concept without implementing scalar type hinting (which is exactly what I tried to avoid)... To be clear, I like the concept of scalar type hinting, and would love to see it implemented. However, given that there is strong sentiment against it on the lists, I'm trying to come up with a solution that allows the problem to be solved without the problems that static typing creates. Thanks, Anthony On Sun, Feb 26, 2012 at 10:14 AM, Clint M Priest cpri...@zerocue.com wrote: I definitely like the idea of being able to cast objects, I've frequently wished to be able to cast an object to an array. I would argue against the single __castTo() and __castFrom() magic methods as large switches get to be difficult to find/read and doesn't support separation. I would prefer something along the lines of C++ such as: Cast From: public __construct(Integer $i); Cast To: public Integer(); This would require function overloading (__construct overloading by type) but with Type Hinting already available for function parameters, this could be done relatively easily I think. Doing this would keep code isolated with smaller functions. -Clint -Original Message- From: Anthony Ferrara [mailto:ircmax...@gmail.com] Sent: Sunday, February 26, 2012 8:57 AM To: internals@lists.php.net Subject: [PHP-DEV] Object Casting - An Alternative to Type Hinting I've gone back and re-read a bunch of the old posts on Type Hinting, and have come to the conclusion that it won't be done any time soon. Not because it doesn't have merit, but because there are at least a few fundamental difficulties that are non-trivial to figure out while still keeping the usefulness. So, I started thinking of a way that we can work around it. One technique that has been passed around is to use object wrappers and pass objects instead of scalars. Such as was suggested in: http://marc.info/?l=php-internalsm=119543188808737w=2 One of the problems associated with this, is that before you work with these types, you need to manually cast them back to the native type they represent. We can try to deal with this problem using __toString, but I don't think that's granular enough to really be of much use in solving this problem... Another method we could use, is if we supported operator overloading in
Re: [PHP-DEV] Object Casting - An Alternative to Type Hinting
On Sun, Feb 26, 2012 at 10:57 PM, Anthony Ferrara ircmax...@gmail.com wrote: I've gone back and re-read a bunch of the old posts on Type Hinting, and have come to the conclusion that it won't be done any time soon. Not because it doesn't have merit, but because there are at least a few fundamental difficulties that are non-trivial to figure out while still keeping the usefulness. So, I started thinking of a way that we can work around it. One technique that has been passed around is to use object wrappers and pass objects instead of scalars. Such as was suggested in: http://marc.info/?l=php-internalsm=119543188808737w=2 One of the problems associated with this, is that before you work with these types, you need to manually cast them back to the native type they represent. We can try to deal with this problem using __toString, but I don't think that's granular enough to really be of much use in solving this problem... Another method we could use, is if we supported operator overloading in objects. That way, we could overload the addition operator to handle the operation. However, this becomes quite problematic, since ordering of operations and interaction with disparate class trees is going to get rather messy (and extremely fragile) quite quick. Let me throw out another possible solution. What if we added two new magic methods to objects: public function __castTo($type); public static function __castFrom($value); With these two methods, we could enable type-hinting by using something very similar to auto-boxing. Let me start with a sample implementation: class Integer { protected $value = 0; public function __construct($value) { $this-value = $value; } public function __castTo($type) { switch ($type) { case 'int': case 'numeric': return $this-value; case 'float': return (float) $this-value; } throw new LogicException('Illegal Cast Operation Performed'); } public static function __castFrom($value) { if (!is_scalar($value)) { throw new LogicException('Illegal Cast Operation Performed'); } return new static((int) $value); } } Now, that enables us to do something like: $int = new Integer(2); echo $int + 2; // 4, since __castTo was called with numeric echo substr(foobar, 0, $int); // fo since __castTo was called with int I have to say, it doesn't get work, thinking this: $mixed1 = new Interger(2); $mixed2 = new Interge(3); $guess_what_type_is = $mixed1 + $mixed2; thanks That demonstrates the __castTo usages. Now for the __castFrom... function foo(Integer $int) { echo $int + 1; } Now, under current rules, calling foo(1) would result in a fatal error. However, we could change that to check if the class being type-hinted for has a __castFrom method on it. If it does, it would attempt to cast the value into that class. So calling foo(1) would actually internally call `Integer::__castFrom(1)`. And since that returns an object of instance Integer, the hint would pass. These two additions would solve a few issues with type-hinting. First off, it solves the cast to vs error if debate on passing a string in the place of an integer. In this case, it would be up to the __castFrom() method to determine that (thereby enabling both worlds possible). Second, it solves the problem of having to wrap clumsy APIs around scalars for hinting purposes ($foo-getInteger() + 1). Third, it is still completely optional... Fourth, it keeps and tries to embrace the dynamic type-cohersion nature of PHP... Now, that's not to say it's not without problems. Here are a few that I can think of: 1. How should it deal with references? If I do `function foo(Integer $int)`, what should happen? - I would argue that if you're trying to reference, the casting functionality should not be expected to work at all. But that introduces some inconsistency there. Not sure how to solve that... 2. Should it support casting from one object to another? Meaning if I pass an SPLInt to something expecting Integer (from two different trees), should __castFrom be called? - I would argue that yes, it should. That would open the door for compatibility layers to be built for cross-framework interaction that happens seamlessly regardless of what was passed in. But it could get a bit interesting, since that also could wind up having really non-obvious side-effects, mainly because of object references... 3. Should class casting then be supported? We can currently do (int) $foo. Should we then be able to specify a class in the cast instead? (Integer) $foo? - I like the concept, but that could be a nightmare to implement as it's hard to tell if it's a class reference or a constant enclosed in () for the parser. And seeing as you can have a constant with the same name as a class, which
Re: [PHP-DEV] Object Casting - An Alternative to Type Hinting
I have to say, it doesn't get work, thinking this: $mixed1 = new Interger(2); $mixed2 = new Interge(3); $guess_what_type_is = $mixed1 + $mixed2; thanks That one is actually pretty straight forward. Since `+` is a numeric operation (with the one exception of array + array), it would call castTo('numeric') on both. Then, the normal type rules would take over. So if it returned an int, the result would be int(5). If it returned a float, it would be float(5)... The case where it would not be trivial to determine would be: $mixed1 = new Integer(2); $guess_what_type_it_is = $mixed1 ^ 1; $guess_what_type_it_is2 = $mixed1 ^ '1'; Since xor operates on both strings and integers, which it should be casted to would be non-trivial to predict. However, we can solve this in the same way that normal type juggling is solved. By being predictable. It doesn't always have to do it correctly (as you want it to do) for each operation, as long as it does it predictably. That way, we can know that xor will default to an integer operation, so you'd have to make sure both are strings to have it be a string operation (which incidentally is what happens now): $string = ((string) $mixed1) ^ '1'; And to be clear, I didn't write a patch for this, because I wanted to discuss this first (rather than go through all the work just to be shot down at first sight). If it's something that's worth investigating, I'd be happy to work on a patch. But I'm not going to go through all that work unless there's buy in from at least some of the core developers. I'm not saying I'm looking for a you do it, and it'll be in, but more of a this is interesting, let's see an implementation before we decide, but the concept sounds interesting/good... Anthony On Sun, Feb 26, 2012 at 10:39 AM, Laruence larue...@php.net wrote: On Sun, Feb 26, 2012 at 10:57 PM, Anthony Ferrara ircmax...@gmail.com wrote: I've gone back and re-read a bunch of the old posts on Type Hinting, and have come to the conclusion that it won't be done any time soon. Not because it doesn't have merit, but because there are at least a few fundamental difficulties that are non-trivial to figure out while still keeping the usefulness. So, I started thinking of a way that we can work around it. One technique that has been passed around is to use object wrappers and pass objects instead of scalars. Such as was suggested in: http://marc.info/?l=php-internalsm=119543188808737w=2 One of the problems associated with this, is that before you work with these types, you need to manually cast them back to the native type they represent. We can try to deal with this problem using __toString, but I don't think that's granular enough to really be of much use in solving this problem... Another method we could use, is if we supported operator overloading in objects. That way, we could overload the addition operator to handle the operation. However, this becomes quite problematic, since ordering of operations and interaction with disparate class trees is going to get rather messy (and extremely fragile) quite quick. Let me throw out another possible solution. What if we added two new magic methods to objects: public function __castTo($type); public static function __castFrom($value); With these two methods, we could enable type-hinting by using something very similar to auto-boxing. Let me start with a sample implementation: class Integer { protected $value = 0; public function __construct($value) { $this-value = $value; } public function __castTo($type) { switch ($type) { case 'int': case 'numeric': return $this-value; case 'float': return (float) $this-value; } throw new LogicException('Illegal Cast Operation Performed'); } public static function __castFrom($value) { if (!is_scalar($value)) { throw new LogicException('Illegal Cast Operation Performed'); } return new static((int) $value); } } Now, that enables us to do something like: $int = new Integer(2); echo $int + 2; // 4, since __castTo was called with numeric echo substr(foobar, 0, $int); // fo since __castTo was called with int I have to say, it doesn't get work, thinking this: $mixed1 = new Interger(2); $mixed2 = new Interge(3); $guess_what_type_is = $mixed1 + $mixed2; thanks That demonstrates the __castTo usages. Now for the __castFrom... function foo(Integer $int) { echo $int + 1; } Now, under current rules, calling foo(1) would result in a fatal error. However, we could change that to check if the class being type-hinted for has a __castFrom method on it. If it does, it would attempt to cast the value into that class. So calling foo(1) would actually internally call `Integer::__castFrom(1)`. And since that returns an object of instance Integer, the hint would pass. These two
Re: [PHP-DEV] Object Casting - An Alternative to Type Hinting
On Sun, 26 Feb 2012 16:39:10 +0100, Laruence larue...@php.net wrote: On Sun, Feb 26, 2012 at 10:57 PM, Anthony Ferrara ircmax...@gmail.com wrote: I have to say, it doesn't get work, thinking this: $mixed1 = new Interger(2); $mixed2 = new Interge(3); $guess_what_type_is = $mixed1 + $mixed2; Actually, this part of the problem can be pretty much be implemented today for internal classes with the cast_object[1] or get[2] handlers. There are of course some difficulties, like the nonexistence of a numeric cast, which, by the way, has caused some trouble because the Zend Engine defaults to cast to an integer in a numerical situation instead of a float. This has causes a known bug in SimpleXML: ?php $xml = XML a6.5/a XML; $sxml = new simplexmlelement($xml); $r = 4 + $sxml; echo $r; //10, not 10.5 The other side (cast from) is more problematic, not entirely satisfactory to the people that have proposed autoboxing in the past, which would like to be able to do $a = 1; $a-blah(). [1] https://wiki.php.net/internals/engine/objects#cast_object [2] https://wiki.php.net/internals/engine/objects#get -- Gustavo Lopes -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] Object Casting - An Alternative to Type Hinting
On 02/26/2012 04:48 PM, Anthony Ferrara wrote: I have to say, it doesn't get work, thinking this: $mixed1 = new Interger(2); $mixed2 = new Interge(3); $guess_what_type_is = $mixed1 + $mixed2; thanks That one is actually pretty straight forward. Since `+` is a numeric operation (with the one exception of array + array), it would call castTo('numeric') on both. Then, the normal type rules would take over. So if it returned an int, the result would be int(5). If it returned a float, it would be float(5)... Or operator-overlading to the rescue? :-) (Okay, I know that idea has been burried a long time ago - but might come in hand here as well. http://bugs.php.net/bug.php?id=9331 http://pecl.php.net/package/operator ) Regards, Stefan -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] Object Casting - An Alternative to Type Hinting
On 26/02/12 15:57, Anthony Ferrara wrote: I've gone back and re-read a bunch of the old posts on Type Hinting, and have come to the conclusion that it won't be done any time soon. Not because it doesn't have merit, but because there are at least a few fundamental difficulties that are non-trivial to figure out while still keeping the usefulness. Can you provide a list? Having clear objectives of what we are intending to fix will help to find a good solution. I suspect that the __cast solution is more complex than needed. And specifically, I forsee having both __castTo() and __castFrom() as a source of conflicts. -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] Object Casting - An Alternative to Type Hinting
I just realised that if it were going to add magic casting, it could as well be done with a spl_autocast_register(), so that you could either cast things when they match, throw an exception, etc. (there should be some default value dynamic typing, so the perfomance wouldn't hurt) . I don't think that's the perfect solution, though. -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] Object Casting - An Alternative to Type Hinting
I like it, at least from a raw conceptual standpoint. I think you might be on to something here, though I'd need to take some time to deliberate on it in more detail. But my initial gut reaction is that this would at very least be a step in the right direction. =) --Kris On Sun, Feb 26, 2012 at 6:57 AM, Anthony Ferrara ircmax...@gmail.comwrote: I've gone back and re-read a bunch of the old posts on Type Hinting, and have come to the conclusion that it won't be done any time soon. Not because it doesn't have merit, but because there are at least a few fundamental difficulties that are non-trivial to figure out while still keeping the usefulness. So, I started thinking of a way that we can work around it. One technique that has been passed around is to use object wrappers and pass objects instead of scalars. Such as was suggested in: http://marc.info/?l=php-internalsm=119543188808737w=2 One of the problems associated with this, is that before you work with these types, you need to manually cast them back to the native type they represent. We can try to deal with this problem using __toString, but I don't think that's granular enough to really be of much use in solving this problem... Another method we could use, is if we supported operator overloading in objects. That way, we could overload the addition operator to handle the operation. However, this becomes quite problematic, since ordering of operations and interaction with disparate class trees is going to get rather messy (and extremely fragile) quite quick. Let me throw out another possible solution. What if we added two new magic methods to objects: public function __castTo($type); public static function __castFrom($value); With these two methods, we could enable type-hinting by using something very similar to auto-boxing. Let me start with a sample implementation: class Integer { protected $value = 0; public function __construct($value) { $this-value = $value; } public function __castTo($type) { switch ($type) { case 'int': case 'numeric': return $this-value; case 'float': return (float) $this-value; } throw new LogicException('Illegal Cast Operation Performed'); } public static function __castFrom($value) { if (!is_scalar($value)) { throw new LogicException('Illegal Cast Operation Performed'); } return new static((int) $value); } } Now, that enables us to do something like: $int = new Integer(2); echo $int + 2; // 4, since __castTo was called with numeric echo substr(foobar, 0, $int); // fo since __castTo was called with int That demonstrates the __castTo usages. Now for the __castFrom... function foo(Integer $int) { echo $int + 1; } Now, under current rules, calling foo(1) would result in a fatal error. However, we could change that to check if the class being type-hinted for has a __castFrom method on it. If it does, it would attempt to cast the value into that class. So calling foo(1) would actually internally call `Integer::__castFrom(1)`. And since that returns an object of instance Integer, the hint would pass. These two additions would solve a few issues with type-hinting. First off, it solves the cast to vs error if debate on passing a string in the place of an integer. In this case, it would be up to the __castFrom() method to determine that (thereby enabling both worlds possible). Second, it solves the problem of having to wrap clumsy APIs around scalars for hinting purposes ($foo-getInteger() + 1). Third, it is still completely optional... Fourth, it keeps and tries to embrace the dynamic type-cohersion nature of PHP... Now, that's not to say it's not without problems. Here are a few that I can think of: 1. How should it deal with references? If I do `function foo(Integer $int)`, what should happen? - I would argue that if you're trying to reference, the casting functionality should not be expected to work at all. But that introduces some inconsistency there. Not sure how to solve that... 2. Should it support casting from one object to another? Meaning if I pass an SPLInt to something expecting Integer (from two different trees), should __castFrom be called? - I would argue that yes, it should. That would open the door for compatibility layers to be built for cross-framework interaction that happens seamlessly regardless of what was passed in. But it could get a bit interesting, since that also could wind up having really non-obvious side-effects, mainly because of object references... 3. Should class casting then be supported? We can currently do (int) $foo. Should we then be able to specify a class in the cast instead? (Integer) $foo? - I like the concept, but that could be a nightmare to implement as it's hard to tell if it's a class reference
Re: [PHP-DEV] Object Casting - An Alternative to Type Hinting
Or operator-overlading to the rescue? :-) Not quite. Especially because with operator overloading done at this level (how it would be implemented in PHP) it's almost impossible to make it consistent: class string { public function overload+($mixed) { return $this-value + $mixed; } } class Integer { public function overload+($mixed) { return $this-value + $mixed; } } $int = new Integer(5); $string = new String(5); echo $int + $string; // 10 echo $string + $int; // 55 While I like the concept of overloading, I don't really think it's solvable in a consistent enough manner that it would work here. On Sun, Feb 26, 2012 at 11:12 AM, Stefan Neufeind neufe...@php.net wrote: On 02/26/2012 04:48 PM, Anthony Ferrara wrote: I have to say, it doesn't get work, thinking this: $mixed1 = new Interger(2); $mixed2 = new Interge(3); $guess_what_type_is = $mixed1 + $mixed2; thanks That one is actually pretty straight forward. Since `+` is a numeric operation (with the one exception of array + array), it would call castTo('numeric') on both. Then, the normal type rules would take over. So if it returned an int, the result would be int(5). If it returned a float, it would be float(5)... Or operator-overlading to the rescue? :-) (Okay, I know that idea has been burried a long time ago - but might come in hand here as well. http://bugs.php.net/bug.php?id=9331 http://pecl.php.net/package/operator ) Regards, Stefan -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] Object Casting - An Alternative to Type Hinting
I fail to see how you would do it via a register function... Unless you mean a call-chain of callbacks to try to cast with a from and a to parameter: spl_autocast_register(function($from, $to) { if ($to == 'Integer') { return new Integer((int) $from); } }); That could have extreme performance penalties, as every callback in the chain (at least up to a valid cast) would then need to be called for every single cast operation. Not to mention that you're now externalizing where the cast happens into a non-obvious and non-extendable spot (meaning that you're removing the possibility of modifying behavior via polymorphism)... I prefer the concept of binding the cast operations (two, for symmetry) to the class itself, as it localizes the functionality to that class, and is quite predictable and extendable. If I missed the point you were trying to make, please elaborate. Thanks, Anthony 2012/2/26 Ángel González keis...@gmail.com: I just realised that if it were going to add magic casting, it could as well be done with a spl_autocast_register(), so that you could either cast things when they match, throw an exception, etc. (there should be some default value dynamic typing, so the perfomance wouldn't hurt) . I don't think that's the perfect solution, though. -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] Object Casting - An Alternative to Type Hinting
Hi, This does not seem like a good way for me ... Think about combining many scripts. It's for example quite usual to use Symfony and parts of Zend Framework together. Think about what will happen if the one framework uses another autocast logic ... Bye Simon 2012/2/27 Anthony Ferrara ircmax...@gmail.com I fail to see how you would do it via a register function... Unless you mean a call-chain of callbacks to try to cast with a from and a to parameter: spl_autocast_register(function($from, $to) { if ($to == 'Integer') { return new Integer((int) $from); } }); That could have extreme performance penalties, as every callback in the chain (at least up to a valid cast) would then need to be called for every single cast operation. Not to mention that you're now externalizing where the cast happens into a non-obvious and non-extendable spot (meaning that you're removing the possibility of modifying behavior via polymorphism)... I prefer the concept of binding the cast operations (two, for symmetry) to the class itself, as it localizes the functionality to that class, and is quite predictable and extendable. If I missed the point you were trying to make, please elaborate. Thanks, Anthony 2012/2/26 Ángel González keis...@gmail.com: I just realised that if it were going to add magic casting, it could as well be done with a spl_autocast_register(), so that you could either cast things when they match, throw an exception, etc. (there should be some default value dynamic typing, so the perfomance wouldn't hurt) . I don't think that's the perfect solution, though. -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php