Wouldn't the simple solution be:

/** @var $stream Item[] */
foreach ($stream as $item) {
    /* ... */
}

On Tuesday, October 16, 2018 at 2:02:21 PM UTC-5, Alan Gabriel Bem wrote:
>
> I think you missed my point - What I want to achieve is to *annotate* 
> somehow that *Stream* is *iterable* over *Item* object and do it in *one 
> place* instead of every place I'm using `Stream` implementation. 
>
> As I mentioned I could enforce using *Iterator* or *IteratorAggregate* (as 
> it opens the way to specify the *Item* as an iterated type... which IDEs 
> understand), but I don't want to do that because actual iteration method 
> should depend on how it fits actual implementation. *Traversable* is 
> enough in this case because, simply speaking, it is marking *Stream* as 
> an object you can *foreach* on, but not telling how. 
>
> wt., 16 paź 2018 o 19:30 Chuck Burgess <demon...@gmail.com <javascript:>> 
> napisał(a):
>
>> I'm tempted to argue that you're *not* sticking to Design By Contract 
>> here, because your two `Stream` implementations do not themselves give the 
>> same contract... at least, the parts of the contract that you're wanting to 
>> be derived by the IDE.
>>
>> Since it's already necessary to use a `/* @var */` comment block to 
>> typehint your local variable, and you don't want to hint specifically on 
>> your two classes, then perhaps you can do this instead:
>>
>> /* @var $stream Stream|Iterator|IteratorAggregate */
>> foreach ($stream as $item) {
>>     $item->...
>> }
>>
>> That leaves you only hinting on interfaces... 
>> CRB
>>
>>
>> On Saturday, October 13, 2018 at 5:06:26 PM UTC-5, Alan Gabriel Bem wrote:
>>>
>>> It is easy if such interface already extends some kind of iterator...
>>>
>>> interface Stream extends IteratorAggregate
>>> {
>>>     /**
>>>      * @return Item[]
>>>      */
>>>     public function getIterator();
>>> }
>>>
>>> ...or... 
>>>
>>> interface Stream extends Iterator
>>> {
>>>     /**
>>>      * @return Item
>>>      */
>>>     public function current();
>>> }
>>>
>>> ...so IDEs have no problems with inferring actual type that variable of 
>>> type `Stream` iterates over...
>>>
>>> /* @var $stream Stream */
>>> foreach ($stream as $item) {
>>>     $item->... // works, *Item* class methods are suggested
>>> }
>>>
>>> ...but what if we want to delay the decision of iteration mechanism? 
>>> Like...
>>>
>>> interface Stream extends Traversable
>>> {}
>>>
>>> ...so later on we can do this:
>>>
>>> class InMemoryStream implements Stream, IteratorAggregate
>>> {
>>>     public function __construct(Item ...$items)
>>>     {
>>>         $this->items = $items;
>>>     }
>>>
>>>     // rest of the code goes here
>>>
>>>     /**
>>>      * @return Item[]
>>>      */
>>>     public function getIterator()
>>>     {
>>>         return new ArrayIterator($this->items);
>>>     }
>>> }
>>>
>>> class DatabaseStream implements Stream, Iterator
>>> {
>>>     // rest of the code goes here
>>>
>>>     public function rewind()
>>>     {
>>>         $this->statement = $this->connection->prepare('SELECT * FROM 
>>> items');
>>>         $this->statement->execute();
>>>         $this->current = $this->statement->fetch(\PDO::FETCH_ASSOC);
>>>         $this->key = 0;
>>>     }
>>>
>>>     public function next()
>>>     {
>>>         $this->current = $this->statement->fetch(\PDO::FETCH_ASSOC);
>>>         $this->key++;
>>>     }
>>>     
>>>     public function key()
>>>     {
>>>         return $this->key;
>>>     }
>>>     
>>>     public function valid()
>>>     {
>>>         return false !== $this->current;
>>>     }
>>>
>>>     /**
>>>      * @return Item
>>>      */
>>>     public function current()
>>>     {
>>>         return new Item($this->current);
>>>     }
>>> }
>>>
>>> Unfortunately IDEs, as can be expected, can't handle this.
>>>
>>> /* @var $stream Stream */
>>> foreach ($stream as $item) {
>>>     $item->... // not enough information for IDEs to suggest type that 
>>> $stream iterates over.
>>> }
>>>
>>> AFAIK at this moment the only solution for such case is to annotate 
>>> variables in user-land... every time.
>>>
>>> /* @var $stream Stream|A[] */
>>> foreach ($stream as $item) {
>>>     $item->... // works
>>> }
>>>
>>> // or worse
>>>
>>> /* @var $stream DatabaseStream */
>>> foreach ($stream as $item) {
>>>     $item->... // works but annotation specifies actual implementation 
>>> which violates Design by Contract principle
>>> }
>>>
>>>
>>>
>>> It bugs me personally, but I would like to hear your opinion on this and 
>>> possible solution.
>>>
>> -- 
>> You received this message because you are subscribed to the Google Groups 
>> "PHP Framework Interoperability Group" group.
>> To unsubscribe from this group and stop receiving emails from it, send an 
>> email to php-fig+u...@googlegroups.com <javascript:>.
>> To post to this group, send email to php...@googlegroups.com 
>> <javascript:>.
>> To view this discussion on the web visit 
>> https://groups.google.com/d/msgid/php-fig/77014da1-8ab9-4042-af9d-eb26deaeaf97%40googlegroups.com
>>  
>> <https://groups.google.com/d/msgid/php-fig/77014da1-8ab9-4042-af9d-eb26deaeaf97%40googlegroups.com?utm_medium=email&utm_source=footer>
>> .
>> For more options, visit https://groups.google.com/d/optout.
>>
>
>
> -- 
> Pozdrawiam,
> Alan Bem
> <http://www.recovery.pl/>
>

-- 
You received this message because you are subscribed to the Google Groups "PHP 
Framework Interoperability Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to php-fig+unsubscr...@googlegroups.com.
To post to this group, send email to php-fig@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/php-fig/c63e44ec-215d-45c4-9d42-77c32663a35f%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to