Hi all, thanks for the valuable feedback!

@Stephen Reay:

>  I like the idea but I find the syntax (both suggestions) less than
great, given that there’s already “ensure a type” syntax, and both
suggestions are already used for other things (casting and foreach)

Note that we already use `as` in other contexts than foreach: in imports
(`use Foo as Bar`) and in traits (`use SomeTrait { foo as bar; }`) , so I
think that reusing the keyword for yet another use case is OK, as long as
it does not conflict.

> Is there some reason (eg ambiguities) a type can’t just be placed before
a variable to ensure a type, similar to a function parameter or typed
property?
> string $foo = 'bar';
> ...
> I’m talking about exactly the same functionality that exists with method
parameters - constraining the type it must conform to when it is declared.
Nothing more nothing less.

I would personnally read this as "this variable is now strongly typed,
INCLUDING later assignments" (which would belong to another feature /
discussion), but as you have later clarified that this is not what you had
in mind, I think that this syntax is then even more confusing than the
other proposals:

    Foo $foo = new Foo();
    $foo = 123; // this would work?

> Using `as` means trying to add type constraints to an iterable in the
foreach would be ridiculously confusing:
> foreach ( $foo as $K as int => $v as string) {...}

Please note that my proposal is specific to class/interface names, not
other types for now (I could consider broadening it if people are
interested in the suggested "as" syntax from Hack).
Anyway with the two syntaxes suggested so far, you would not inline it in
the foreach, but explicitly write:

    foreach ($foos as $foo) {
        $foo = (Foo) $foo;
        // or
        $foo = $foo as Foo;
    }

@Andreas Hennings:

> If I remember correctly, an object pointer (object variable) in Java has
a type independent of the object it points to. The pointer type restricts
the range of object types that can be pointed to from the variable.
> You can cast the pointer type (variable type) to let a variable of
different object pointer type store the same object, as long as the type is
compatible.
> In PHP, variables have no type on language level, so casting would indeed
be a misleading concept. Unless we want to change this.

You have a point for sure, but as I said above, I don't feel like this
makes it incompatible with casting semantics.

In Java, casting to a class/interface name:

1. ensures that the variable holds an instance of this class/interface
2. changes the pointer type, which affects later usage of the object

In PHP, you'd just scratch point #2 which is irrelevant. Is this a good
enough reason to stop using the casting syntax? I'm not sure.

@Sebastian Bergmann:

> Today's equivalent is, at least for me, is this one-liner:
> assert($service instanceof EmailService);

Let's be picky: this is actually a two-liner, a second line after the
variable declaration ;-)

> This way the IDE knows what type $service is supposed to be and there
will
> be an exception at runtime (given the appropriate configuration) when
this
> is not the case.

That's a fair point regarding the IDE. The exception at runtime however,
becomes strongly dependent on PHP configuration.
We're also losing the advantage of an explicit language construct, that I
suspect could be later used by the JIT compiler to generate more efficient
machine code by knowing the type of the variable at this point at compile
time (I'd love to get feedback on this point from Dmitry).

> Personally, I prefer hand-written factories that have an explicit
> createEmailService() method with a :EmailService return type declaration,
> for example, over the implicitness of a dependency injection container as
> the latter disguises and obscures dependencies.

We're entering the realm of patterns here; I'm a big fan of IoC myself and
even though I use it a lot in my apps, I still find myself calling
`$diContainer->get()` more often than not, for example in quick prototypes
or CLI scripts. Same thing for ORMs: you may have a full-blown repository
for each entity with a strongly typed `find() : ClassName` method, but you
may also need to call `$entityManager->find()` directly from time to time.
There are also plenty of other use cases in PHP, where you get a variable
from a losely typed source (array or whatever), but somehow know that it
should be of a given type.

- Ben


On Tue, 23 Apr 2019 at 07:58, M. W. Moe <mo.mu....@gmail.com> wrote:

> Hello,
>
> Sebastian yes; interface or abstract have been somehow created for that
> purpose; even if I find people abusing of those constructs; now if your
> container is generalized and represents dynamic data; for instance like a
> Message class
> it could hold dynamic data types;
>
> let say:
> // abstract public offsetGet
> <https://www.php.net/manual/en/arrayaccess.offsetget.php> ( mixed
> <
> https://www.php.net/manual/en/language.pseudo-types.php#language.types.mixed
> >
>  $offset ) : mixed
> <
> https://www.php.net/manual/en/language.pseudo-types.php#language.types.mixed
> >
> $service = $diContainer['email.service'] of ?EmailService; // else throw
> TypeError(this type instead of null or EmailService)
>
>
> On Mon, Apr 22, 2019 at 10:07 PM Sebastian Bergmann <sebast...@php.net>
> wrote:
>
> > Am 22.04.2019 um 23:47 schrieb Benjamin Morel:
> > > These combine into a third advantage: readability. Today's equivalent
> of
> > > the above one-liner could be:
> > >
> > >      /** @var EmailService $service */
> > >      $service = $diContainer->get('email.service');
> > >      if (! $service instanceof EmailService) {
> > >          throw new TypeError('Expected instance of EmailService, ...');
> > >      }
> >
> > Today's equivalent is, at least for me, is this one-liner:
> >
> >      assert($service instanceof EmailService);
> >
> > This way the IDE knows what type $service is supposed to be and there
> will
> > be an exception at runtime (given the appropriate configuration) when
> this
> > is not the case.
> >
> > Personally, I prefer hand-written factories that have an explicit
> > createEmailService() method with a :EmailService return type declaration,
> > for example, over the implicitness of a dependency injection container as
> > the latter disguises and obscures dependencies.
> >
> > --
> > PHP Internals - PHP Runtime Development Mailing List
> > To unsubscribe, visit: http://www.php.net/unsub.php
> >
> >
>

Reply via email to