On 2 January 2015 at 14:00, Andrea Faulds <a...@ajf.me> wrote:

> Hi Marco,
>
> > On 2 Jan 2015, at 09:16, Marco Pivetta <ocram...@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.
>

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 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.
>

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’t think the cast-like syntax is a particularly good idea. It’s
> 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’s misleading, as well: we don’t do an explicit cast. If 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’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.
>

~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’d 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 = '';
> >     $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?


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’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.
>

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/

Reply via email to