Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:93551 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 3639 invoked from network); 26 May 2016 07:53:06 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 26 May 2016 07:53:06 -0000 Authentication-Results: pb1.pair.com smtp.mail=php@fleshgrinder.com; spf=permerror; sender-id=unknown Authentication-Results: pb1.pair.com header.from=php@fleshgrinder.com; sender-id=unknown Received-SPF: error (pb1.pair.com: domain fleshgrinder.com from 77.244.243.85 cause and error) X-PHP-List-Original-Sender: php@fleshgrinder.com X-Host-Fingerprint: 77.244.243.85 mx104.easyname.com Received: from [77.244.243.85] ([77.244.243.85:40468] helo=mx206.easyname.com) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id D7/66-14311-16BA6475 for ; Thu, 26 May 2016 03:53:05 -0400 Received: from cable-81-173-133-15.netcologne.de ([81.173.133.15] helo=[192.168.178.20]) by mx.easyname.com with esmtpsa (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.84_2) (envelope-from ) id 1b5q6H-0004Pp-IJ; Thu, 26 May 2016 07:53:02 +0000 Reply-To: internals@lists.php.net References: <7B.12.14311.F79C5475@pb1.pair.com> <1b12b09f-f190-dca0-51d9-468e9c571268@fleshgrinder.com> <4ec823c6-b039-fc91-7c78-60d67719cd81@gmail.com> <00482771-3a07-06cf-ee8d-cd83a301c7e7@fleshgrinder.com> To: Stanislav Malyshev , internals@lists.php.net, Andrea Faulds Cc: Marco Pivetta , Benoit Schildknecht , Niklas Keller Message-ID: <1ac579b7-6bf3-f362-c045-0261abcfa17c@fleshgrinder.com> Date: Thu, 26 May 2016 09:52:41 +0200 User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:45.0) Gecko/20100101 Thunderbird/45.1.0 MIME-Version: 1.0 In-Reply-To: Content-Type: multipart/signed; micalg=pgp-sha256; protocol="application/pgp-signature"; boundary="i0UTTwLoBx3cauPwhjfI1JBanW8JTurXD" X-ACL-Warn: X-DNSBL-BARRACUDACENTRAL Subject: Re: [PHP-DEV] [RFC][Vote] Typed Properties From: php@fleshgrinder.com (Fleshgrinder) --i0UTTwLoBx3cauPwhjfI1JBanW8JTurXD Content-Type: multipart/mixed; boundary="4Dg2liA6lx0p6gTfleBqKQvsIL5ieowWV" From: Fleshgrinder Reply-To: internals@lists.php.net To: Stanislav Malyshev , internals@lists.php.net, Andrea Faulds Cc: Marco Pivetta , Benoit Schildknecht , Niklas Keller Message-ID: <1ac579b7-6bf3-f362-c045-0261abcfa17c@fleshgrinder.com> Subject: Re: [PHP-DEV] [RFC][Vote] Typed Properties References: <7B.12.14311.F79C5475@pb1.pair.com> <1b12b09f-f190-dca0-51d9-468e9c571268@fleshgrinder.com> <4ec823c6-b039-fc91-7c78-60d67719cd81@gmail.com> <00482771-3a07-06cf-ee8d-cd83a301c7e7@fleshgrinder.com> In-Reply-To: --4Dg2liA6lx0p6gTfleBqKQvsIL5ieowWV Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable On 5/26/2016 12:03 AM, Stanislav Malyshev wrote: > Hi! >=20 >> Andrea already said that we would not use it for untyped properties, >> hence, no BC. >=20 > Again, it's not that simple. Properties are not local. That means any > code that can deal with a class that may have typed properties (which > may be library class, for example, so you don't even know what it has > inside) has to deal with the possibility of it being of the new type. S= o > if the old code uses is_null($object->foo) as means to check if the > value wasn't initialized, and it's no longer null, then that code is > broken and needs to be rewritten. That's a BC break. Yes, it will never= > happen if you never use typed properties, and never use any libraries > that might use typed properties, but then what's the point of the whole= > thing? The point of BC is that if you don't use new features, you don't= > have to change your code and it will keep working. With the proposed > solution, it won't be the case. >=20 >> It is not the same as null, very similar, but definitely not the same.= >> Think of it in DB terms: >> >> | table | >> | ----- | >> | id | >> >> SELECT name FROM table; >> >> That's not null, it's not defined (undefined, unset, ...). In other >> words, null is a value and undefined/unset a state. >=20 > "name" is not a value, as in if you do that in SQL, you don't get a > value, you get an error. Same as if you wrote "please can I haz a > pony?". It's just something the SQL can not give you, so it produces an= > error. What is proposed here, however, is a PHP type, not an error. > That's a different thing - if you have a variable, then you have to hav= e > a value, and if you have a value, then you have to have a type. >=20 I understand where you are getting at. Another proposal after giving this some more thought. var_dump($a); // null + E_NOTICE Undefined var_dump(isset($a)); // false var_dump(is_null($a)); // true + E_NOTICE Undefined var_dump($a =3D=3D null); // true + E_NOTICE Undefined var_dump($a =3D=3D=3D null); // true + E_NOTICE Undefined= $a =3D ['x' =3D> null]; var_dump($a['x']); // null var_dump(isset($a['x']); // false var_dump(array_key_exists($a['x'])); // true var_dump(is_null($a['x']); // true var_dump($a['x'] =3D=3D null); // true var_dump($a['x'] =3D=3D=3D null); // true $b =3D (object) []; var_dump($b->x); // null + E_NOTICE Undefined var_dump(isset($b->x)); // false var_dump(property_exists($b, 'x')); // false var_dump(is_null($b->x)); // true + E_NOTICE Undefined var_dump($b->x =3D=3D null); // true + E_NOTICE Undefined var_dump($b->x =3D=3D=3D null); // true + E_NOTICE Undefined= $c =3D new class { public int $x; }; var_dump($c->x); // null + E_NOTICE Uninitialized var_dump(isset($c->x)); // false var_dump(property_exists($c, 'x')); // true var_dump(is_null($c->x)); // true + E_NOTICE Uninitialized var_dump($c->x =3D=3D null); // true + E_NOTICE Uninitializ= ed var_dump($c->x =3D=3D=3D null); // true + E_NOTICE Uninitial= ized $d =3D new class { public ?int $x; }; var_dump($d->x); // null + E_NOTICE Uninitialized var_dump(isset($d->x)); // false var_dump(property_exists($d, 'x')); // true var_dump(is_null($d->x)); // true + E_NOTICE Uninitialized var_dump($d->x =3D=3D null); // true + E_NOTICE Uninitializ= ed var_dump($d->x =3D=3D=3D null); // true + E_NOTICE Uninitial= ized $e =3D new class { public ?int $x =3D null; }; var_dump($e->x); // null var_dump(isset($e->x)); // false var_dump(property_exists($e, 'x')); // true var_dump(is_null($e->x)); // true var_dump($e->x =3D=3D null); // true var_dump($e->x =3D=3D=3D null); // true /* {{{ PHP 7.1 */ $f =3D new class { public $x; }; var_dump($f->x); // null var_dump(isset($f->x)); // true + E_STRICT Uninitialized var_dump(property_exists($f, 'x')); // true var_dump(is_null($f->x)); // true var_dump($f->x =3D=3D null); // true var_dump($f->x =3D=3D=3D null); // true /* }}} */ /* {{{ PHP 8 */ $g =3D new class { public $x; }; var_dump($g->x); // null + E_NOTICE Uninitialized var_dump(isset($g->x)); // false var_dump(property_exists($g, 'x')); // true var_dump(is_null($g->x)); // true + E_NOTICE Uninitialized var_dump($g->x =3D=3D null); // true + E_NOTICE Uninitializ= ed var_dump($g->x =3D=3D=3D null); // true + E_NOTICE Uninitial= ized /* }}} */ The only thing I personally dislike is the fact that there is no counterpart to isset(). This means that one cannot create a positive conditional that checks for the opposite case without raising an E_NOTICE= =2E class T { private int $x; public function getX() { if (isset($this-x) =3D=3D=3D false) { $this->x =3D 42; } return $this->x; } } However, one could argue that empty() is good enough at this point -- despite the fact that many values are considered empty that might be valid values in other circumstances -- because we want to know the uninitialized case here. From the manual: > The following things are considered to be empty: [...] a variable > declared, but without a value > > --- https://secure.php.net/function.empty class T { private int $x; public function getX() { if (empty($this->x)) { $this->x =3D 42; } return $this->x; } } I could live with that. Note that the behavior of isset() and empty() was already once changed during the 5.4 feature release! I am proposing to change it with a major version for existing code and only emitting an E_STRICT till then. This is not even close as brutal as that behavioral change back then but other than that pretty much the same change. This time it just affects objects and not associative arrays. --=20 Richard "Fleshgrinder" Fussenegger --4Dg2liA6lx0p6gTfleBqKQvsIL5ieowWV-- --i0UTTwLoBx3cauPwhjfI1JBanW8JTurXD Content-Type: application/pgp-signature; name="signature.asc" Content-Description: OpenPGP digital signature Content-Disposition: attachment; filename="signature.asc" -----BEGIN PGP SIGNATURE----- Version: GnuPG v2 iQIcBAEBCAAGBQJXRqtRAAoJEOKkKcqFPVVrS8IQAJuaBthgFzXxOwog6Xbfd5yl stp6I3upaIxDvNONm8z/wRzzXeea+vLYn5aoWc/2PLM9XtpyBWd1lIxkHVNWVavj gYz/2c7lkqYr/ggwDoIOc480dsGbl0ynEopvkyWTohIfRn6gsso+aahelWPuMiFi 0/oYuOaZP3QRYX6C/B5NcTg2a52chyZ79yvIlv6RPStFf23Lm2Rgm5HxV7/nMkrx qZ4nH6e4KwlO8JoOAvVZmXQBepg4R9iPDgxEe+dPHkx5jDMbBCw4J+B+vwMKn2B8 ZygpJeDNBzN809RvIFxfLXSB8BJ4IEH03CmKkTCopOwbR5T0fU3/nEjDQXheXGAP +JSWiQVkaf/hIXp6pUNbNeGNrueYxl9WawCe+8nYV5D/EYfNuO5ha1Q3CxrRZBK+ pOnkHH6nnt34KuUuvvhT866Occgp+S9uG2DfCjh6vB4Wou77UJh3Y/YOzjZhDJpD Ch3+sTupVrWtX6n/W1QcuVxy23qWSC6HhlF3sAo/qePjbIzlkEoQorPzbGjnA0Rp gQMKu/gWqrRaVbshzuUziPc/UHvEGli56hgUfL64z0eRkW7+gJodWk6TUuodU7PB iPNaupMKtL6XYYSaHje3oz6bk5FbhLDOUKHV8er4wLQ+lFpBwLXfh6RAAktDetjc 0zOsUdK1UqSA/PVZf8Fj =7N90 -----END PGP SIGNATURE----- --i0UTTwLoBx3cauPwhjfI1JBanW8JTurXD--