Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:80092 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 66349 invoked from network); 2 Jan 2015 13:15:52 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 2 Jan 2015 13:15:52 -0000 Authentication-Results: pb1.pair.com header.from=ocramius@gmail.com; sender-id=pass Authentication-Results: pb1.pair.com smtp.mail=ocramius@gmail.com; spf=pass; sender-id=pass Received-SPF: pass (pb1.pair.com: domain gmail.com designates 74.125.82.47 as permitted sender) X-PHP-List-Original-Sender: ocramius@gmail.com X-Host-Fingerprint: 74.125.82.47 mail-wg0-f47.google.com Received: from [74.125.82.47] ([74.125.82.47:45113] helo=mail-wg0-f47.google.com) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id B4/E0-61219-60A96A45 for ; Fri, 02 Jan 2015 08:15:51 -0500 Received: by mail-wg0-f47.google.com with SMTP id n12so24155762wgh.20 for ; Fri, 02 Jan 2015 05:15:47 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:in-reply-to:references:from:date:message-id:subject:to :cc:content-type; bh=Ee6t0MD1C5P6aZsiGRGyFqVrRYtRlCkzO0PKdXlH7PE=; b=zrvvSIBZIOA4p+D+eHRsh/jv91SUlcR1/WSHActkU4CfBR8gRyfBL6RX2T8x/9VphR SxbekYEu09US/U23n6ufJPu9e67F9pJ7wBFdU9YrDpp1RoHYCeblINjVydvojjhF0hcI dxPXrgbuyVNOZtx0qb7wZ0OqFQ7P6ToaufHPrdrjEDrynVbDqOc+Iq2Y0QFrD0D7sc5i gtXWqGZoM/GyyLk/y5HG/LgIaATTj3BD3KLmVWWFqU/fL7St3lGgd/EdOD/7amAkwMb6 IO0OSW0hMeMKuwVIorWOt3XD6ipDbEDo5IIeDIMZTyVOa4K4T4LN54lENkLPJCY6eCWJ MTcg== X-Received: by 10.194.89.39 with SMTP id bl7mr83311306wjb.76.1420204547665; Fri, 02 Jan 2015 05:15:47 -0800 (PST) MIME-Version: 1.0 Received: by 10.194.82.163 with HTTP; Fri, 2 Jan 2015 05:15:27 -0800 (PST) In-Reply-To: <458FFDA4-032E-46D9-BE93-E7307F98A1E6@ajf.me> References: <41D5BB0B-73AF-488E-968D-90B2878E3178@ajf.me> <20150101164402.EB1442605AB@dd15934.kasserver.com> <54A5DFCE.6030307@gmail.com> <458FFDA4-032E-46D9-BE93-E7307F98A1E6@ajf.me> Date: Fri, 2 Jan 2015 14:15:27 +0100 Message-ID: To: Andrea Faulds Cc: Stanislav Malyshev , Thomas Bley , Nikita Popov , PHP Internals List Content-Type: multipart/alternative; boundary=047d7bf10a4a9275a6050bab23ad Subject: Re: [PHP-DEV] [RFC] Scalar Type Hints From: ocramius@gmail.com (Marco Pivetta) --047d7bf10a4a9275a6050bab23ad Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: quoted-printable On 2 January 2015 at 14:00, Andrea Faulds wrote: > Hi Marco, > > > On 2 Jan 2015, at 09:16, Marco Pivetta wrote: > > > > > > I'm not sure why everyone is still taking the PHP manual as a good > reference about how to write software: PHP internal functions are one of > the main reason why this language is under-appreciated. > > > > The manual is pulling the concepts of `int`, `string` and so on out of > thin air, whereas the correct syntax in those cases is > `int|string|Stringable`, with explicit explanation of what those strings > should look like. > > I don=E2=80=99t see why the manual is wrong. Yes, in a strictly-typed lan= guage > which allows no conversion of arguments, foobar(int $foo) wouldn=E2=80=99= t have the > behaviour PHP exhibits. Yet PHP is not a strictly-typed language, and > weakly-typed parameters are hardly a novel concept. The language that PHP > is implemented in, C, also has this. And yet, C does not have this: > > void foobar(char|unsigned char|short|unsigned short|int|unsigned > int|long|unsigned long|long long|unsigned long > long|float|double|_Bool|void* foo) > > Why? Because in C, implicit conversions between parameter types are > permitted. PHP has the same thing for its internal/extension functions. T= he > manual isn=E2=80=99t wrong. > The manual is wrong since it specifies a strict hint for something that is `mixed`. It is still useful tho, since it's telling us "it accepts" integer-ish values there. It's purely for documentation purposes though, it is by far dictating the actual implementation. > > This is constraining. Constraining has nothing to do with validation an= d > casting: mixing the concepts of type-juggling, validation and constrainin= g > is a huge mess (which I don't like, but it's better than having nothing), > and it would better be off using a syntax like: > > Argument types do not necessarily exist purely to error on invalid input. > They also exist for documentation purposes and, in languages like C, > implicit conversion. > No, argument types exist to prevent mistakes: they prevent invalid values to cross validation boundaries of the application. Documentation purposes are purely secondary, we already have phpdoc for that. > > public function __construct(ProductId $productId, (int) $amount) > > > > This makes the difference **much more clear**, as that `(int)` is not a > constraint, it's a different, broader concept. > > I don=E2=80=99t think the cast-like syntax is a particularly good idea. I= t=E2=80=99s > inconsistent with our manual conventions (then again, many other things > are). Again with the manual (*sigh*): the manual comes AFTER the code has been written. > It=E2=80=99s misleading, as well: we don=E2=80=99t do an explicit cast. I= f it was an > explicit cast, literally any value would be accepted. Agree on that, then give it a different name and/or syntax, but it's not a constraint then. > But that=E2=80=99s not the case at all, the weakly-typed parameters that = extension > functions have do not accept any value. Instead, they accept the desired > type, and a limited range of convertible values of other scalar types. > ~int ~float and ~string are fine as well here IMO, if you think that (int) (float) and (string) are misleading. > > Additionally, the BC break concern of strict type-hinting and classes > named `String`, `Int` and `Bool` (and similars) is delayed until we get > strict type-hints, as the syntax is currently not allowed by the language > and doesn't present any BC issues (http://3v4l.org/3Fqdh): > > I=E2=80=99d rather not delay it. We probably should have reserved syntax = for > scalar hints ages ago. > It was just a plus for getting it done to move over to actual type specifications :-) Introducing a BC break always increases the likeliness of a change being accepted by a huge lot. > > @Andrea: as for the "strict" and "non-strict" PHP suggestion you had > before, please don't do that. Take following example: > > > > function repeat(int $amount, (string) $value) { > > $acc =3D ''; > > $i =3D 0; > > > > while ($i < $amount) { > > $i +=3D 1; > > $acc .=3D $value; > > } > > > > return $acc; > > } > > > > As you can see, mixing implicit cast and strict constraining behaviors > is perfectly fine in this case, so please don't include contextual > switches: that would be even worse IMO. > > I don=E2=80=99t understand why that particular example makes sense. Since= it=E2=80=99s > producing a string value, surely $value should always be a string? The difference is that $amount must always be an integer (not integer-ish) value, whereas $value must be a stringable value, and the cast would happen at call-time, not at every loop (very relevant for instances of classes implementing `__toString()`, as the call happens only once). > I really don=E2=80=99t like the idea of mixing strong- and weakly-typed > parameters. We should be consistent. Otherwise, we are imposing too high = a > mental burden on programmers, who will now need to remember which > parameters are strongly-typed and which parameters are weakly-typed. > I think the example I just gave you is very consistent, explicit and easy to understand. Additionally, I don't see any particular mental burden except for having to know that $value will be cast to a string if it isn't. If there is any mental burden, it's mainly introduced by the proposed RFC, whereas strict checking would remove any doubts about what $value can be. Marco Pivetta http://twitter.com/Ocramius http://ocramius.github.com/ --047d7bf10a4a9275a6050bab23ad--