Re: [RFC] Scalar Type Hints
| From: | Andrea Faulds | Date: | Fri, 02 Jan 2015 13:00:37 +0000 |
| Subject: | Re: [RFC] Scalar Type Hints | ||
| References: | 1 2 3 4 5 6 | Groups: | php.internals |
| Request: | Send a blank email to internals+get-80090@lists.php.net to get a copy of this message | ||
Hi Marco,
> On 2 Jan 2015, at 09:16, Marco Pivetta <ocramius@gmail.com> 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’t see why the manual is wrong. Yes, in a strictly-typed language which allows no conversion
of arguments, foobar(int $foo) wouldn’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. The manual isn’t wrong.
> This is constraining. Constraining has nothing to do with validation and casting: mixing the
> concepts of type-juggling, validation and constraining 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.
> 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’t think the cast-like syntax is a particularly good idea. It’s inconsistent with our
manual conventions (then again, many other things are). It’s misleading, as well: we don’t do an
explicit cast. If it was an explicit cast, literally any value would be accepted. But that’s 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.
> 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’d rather not delay it. We probably should have reserved syntax for scalar hints ages ago.
> @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 = '';
> $i = 0;
>
> while ($i < $amount) {
> $i += 1;
> $acc .= $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’t understand why that particular example makes sense. Since it’s producing a string value,
surely $value should always be a string? I really don’t 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.
Thanks.
--
Andrea Faulds
http://ajf.me/