FAQ

On 2 January 2015 at 01:01, Stanislav Malyshev 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/

Search Discussions

Discussion Posts

Previous

Follow ups

Related Discussions

People

Translate

site design / logo © 2019 Grokbase