Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:58097 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 72086 invoked from network); 26 Feb 2012 21:53:57 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 26 Feb 2012 21:53:57 -0000 Authentication-Results: pb1.pair.com smtp.mail=kris.craig@gmail.com; spf=pass; sender-id=pass Authentication-Results: pb1.pair.com header.from=kris.craig@gmail.com; sender-id=pass Received-SPF: pass (pb1.pair.com: domain gmail.com designates 209.85.220.170 as permitted sender) X-PHP-List-Original-Sender: kris.craig@gmail.com X-Host-Fingerprint: 209.85.220.170 mail-vx0-f170.google.com Received: from [209.85.220.170] ([209.85.220.170:38430] helo=mail-vx0-f170.google.com) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id E7/15-40985-2F9AA4F4 for ; Sun, 26 Feb 2012 16:53:55 -0500 Received: by vcbfo14 with SMTP id fo14so204500vcb.29 for ; Sun, 26 Feb 2012 13:53:52 -0800 (PST) Received-SPF: pass (google.com: domain of kris.craig@gmail.com designates 10.220.142.5 as permitted sender) client-ip=10.220.142.5; Authentication-Results: mr.google.com; spf=pass (google.com: domain of kris.craig@gmail.com designates 10.220.142.5 as permitted sender) smtp.mail=kris.craig@gmail.com; dkim=pass header.i=kris.craig@gmail.com Received: from mr.google.com ([10.220.142.5]) by 10.220.142.5 with SMTP id o5mr7044902vcu.68.1330293232104 (num_hops = 1); Sun, 26 Feb 2012 13:53:52 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=mime-version:in-reply-to:references:date:message-id:subject:from:to :cc:content-type; bh=XutXz2uZfcoLZnd2tr4eBsDxs+Rh0HO00aPfyrvD8R4=; b=hK+eOZUwP67is0D7lSla9GAA31WPlHnKL1qiPdtgLj+ks4dyN9uSy+KD4eM/hsrUmN Q9jEyZ6fSFK6Mjv/PSriEDbOc2qTGmBGB4a2q1UOQAgYXXtR5W/Rc4cmQkmwCLuVlrt9 PsLC7M3OWPNjm2JRJntcbfLeLUkqmCK7AdwYg= MIME-Version: 1.0 Received: by 10.220.142.5 with SMTP id o5mr5629220vcu.68.1330293231953; Sun, 26 Feb 2012 13:53:51 -0800 (PST) Received: by 10.52.91.5 with HTTP; Sun, 26 Feb 2012 13:53:51 -0800 (PST) In-Reply-To: References: Date: Sun, 26 Feb 2012 13:53:51 -0800 Message-ID: To: Anthony Ferrara Cc: internals@lists.php.net Content-Type: multipart/alternative; boundary=f46d04388de989a60e04b9e507ec Subject: Re: [PHP-DEV] Object Casting - An Alternative to Type Hinting From: kris.craig@gmail.com (Kris Craig) --f46d04388de989a60e04b9e507ec Content-Type: text/plain; charset=ISO-8859-1 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 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-internals&m=119543188808737&w=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 or a constant enclosed > in () for the parser. And seeing as you can have a constant with the > same name as a class, which should take precedence? > > 4. Should __toString still be called for string contexts? Or would > the presence of __castTo then negate the existance of __toString. So > if you don't implement __castTo(), __toString() would still be called > for a string cast. But if you do, __castTo would be called instead... > It would then work for backwards compatibility, while enabling > __toString to be eventually deprecated in favor of __castTo (not for a > long time mind you, but eventually, possibly 6 or 7)... > > What do you think? > > Anthony > > -- > PHP Internals - PHP Runtime Development Mailing List > To unsubscribe, visit: http://www.php.net/unsub.php > > --f46d04388de989a60e04b9e507ec--