On 2 January 2015 at 01:01, Stanislav Malyshev <smalys...@gmail.com> wrote:

> Hi!
>
> > The problem is that the current proposed hints/casts are deviating from
> the
> > type-hints that we are used to, therefore this particular feature should
>
> Let's check the manual we're used to.
> http://php.net/manual/en/function.substr.php
>
> string substr ( string $string , int $start [, int $length ] )
>
> What "string" and "int" mean there? How they work? What we're
> "deviating" from?


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.

This is what you currently do in a real-world scenario (due to the lack of
hints for internal types):

class Shipment
{
    public function __construct(ProductId $productId, $amount)
    {
        if (! is_int($amount)) {
            throw new InvalidArgumentException(sprintf('Provided $amount
must be integer, %s given', gettype($amount)));
        }

        $this->productId = $productId;
        $this->amount    = $amount;
    }
}

No allowance of weird values passed in: why would my software ever pass an
invalid $amount to my constructor? That's where I'd put a hard-failing
assertion instead.

This is what I'd like it to be:

class Shipment
{
    public function __construct(ProductId $productId, int $amount)
    {
        $this->productId = $productId;
        $this->amount    = $amount;
    }
}

Following code MUST cause a hard failure:

new Shipment($bananasId, '1 of a whole lot');

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:


class Shipment
{
    public function __construct(ProductId $productId, (int) $amount)
    {
        $this->productId = $productId;
        $this->amount    = $amount;
    }
}

This makes the difference **much more clear**, as that `(int)` is not a
constraint, it's a different, broader concept.

I'd rather have the new behavior suggested by Andrea with a syntax that
makes this subtle yet gigantic difference explicit.

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):

function sum((float) $a, (float) $b) { }

>From an implementation perspective, it should just be a parser change.

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


Marco Pivetta

http://twitter.com/Ocramius

http://ocramius.github.com/

Reply via email to