Re: [PHP-DEV] Object Casting - An Alternative to Type Hinting

2012-02-28 Thread jpauli
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

2012-02-28 Thread Anthony Ferrara
 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

2012-02-28 Thread Richard Lynch
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

2012-02-28 Thread Anthony Ferrara
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

2012-02-28 Thread Kris Craig
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

2012-02-27 Thread Richard Lynch
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

2012-02-27 Thread Richard Lynch
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

2012-02-27 Thread Anthony Ferrara
 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

2012-02-27 Thread Ángel González
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

2012-02-27 Thread Richard Lynch
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

2012-02-27 Thread Matthew Weier O'Phinney
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

2012-02-27 Thread Anthony Ferrara
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

2012-02-27 Thread Anthony Ferrara
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

2012-02-26 Thread Clint M Priest
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

2012-02-26 Thread Anthony Ferrara
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

2012-02-26 Thread Laruence
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

2012-02-26 Thread Anthony Ferrara
 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

2012-02-26 Thread Gustavo Lopes

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

2012-02-26 Thread Stefan Neufeind
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

2012-02-26 Thread Ángel González
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

2012-02-26 Thread Ángel González
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

2012-02-26 Thread Kris Craig
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

2012-02-26 Thread Anthony Ferrara
 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

2012-02-26 Thread Anthony Ferrara
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

2012-02-26 Thread Simon Schick
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