On 26 January 2018 at 01:06, Michael Morris <tendo...@gmail.com> wrote:

>
> On Thu, Jan 25, 2018 at 4:11 PM, Levi Morrison <le...@php.net> wrote:
> >
> > Our iterators cannot always be reliably rewound, such as
> > when using generators. Checking that the generator returns only
> > strings would consume all the input and would therefore be useless.
>
>
> True - I hadn't thought of those. But as of PHP 7 generators can type
> declare their return value.  So, given `$a instanceof iterable<string>`, if
> $a is a reference to a generator, then the engine could check the return
> type declaration and only give true on a match without attempting to use
> the generator.
>
> We can follow this pattern farther - The return of an
> ArrayAccess::offsetGet and Iterator::current() can be similarly tested by
> instanceof rather than actually pulling data from these methods.
>
> We are having the return rely on the promise of the code, but in each case
> TypeError would be raised anyway if it breaks it's promise to instanceof so
> errors aren't being avoided.
>


The more angles we approach this, the more it looks like generics, or at
least the same basis. For instance, what you're describing here is that
Iterator<string> would act like an extra interface that restricted the
return type of current() to string. With full userland generics, that would
actually be declarable like this:

interface Iterator<T> extends Iterator {
    public function current(): T;
    public function next(): T;
}

Which would basically be a template so that Iterator<string> created an
appropriately constrained interface, which you can actually create already:

interface Iterator__string extends Iterator {
    public function current(): string;
    public function next(): string;
}

(You could actually use an auto-loader hack to do a lot of generics this
way.)

The main differences I can see between this and your suggestion are:

- If it's an actual interface, the class's definition would need to
explicitly list that it implements it. The wording you used implied that it
might be more implicit, and automatically label the class as an
"iterable<string>" if the signatures matched.
- The iterable<string> syntax would be able to cover arrays as well as
Iterators. We might decide that just as "iterable" stands for "Iterator or
array", "iterable<string>" stands for "Iterator<string> or string[]".
However, I think having "string[]" was previously rejected because of the
cost of checking every element of the array, particular when the type is
something slower to check, like "callable[]".

I think this fits with where Derick was going earlier: we could have
pseudo-generic interfaces like Iterator<string> internally without a full
generics implementation. As long as the syntax and semantics were
compatible, these could then be a stepping-stone to full generics being
added later.

Regards,
-- 
Rowan Collins
[IMSoP]

Reply via email to