in reply to Re^4: Using lazy list with a for loop
in thread Using lazy list with a for loop

> I think that syntax would be the biggest penalty since it would confuse the users.

hence you need to switch to while and add an iterator method ->each to your API °

while ( my ($widget) = $api->each( $item->{sets}{widgets} ) ) { . +.. }

the iterator will be exhausted as soon as ->each returns an empty list.

Cheers Rolf
(addicted to the 𐍀𐌴𐍂𐌻 Programming Language :)
Wikisyntax for the Monastery

°) like others already suggested

Replies are listed 'Best First'.
Re^6: Using lazy list with a for loop
by ikegami (Patriarch) on Jan 03, 2023 at 04:18 UTC

    That has all the problems of the each builtin.

    Better to have a generator creator and user.

    my $iter = $api->get_widgets_iter(); while ( my ( $widget ) = $iter->() ) { ... }
      I agree there are some edge cases to consider depending on the use-case... and I don't know the OPs use cases good enough.

      But because of cleaner scope and loop-control statements I'd rather prefer

      for (my $iter = get_iter(); my ( $widget ) = $iter->(); ) { ... }

      over

      my $iter = get_iter(); while ( my ( $widget ) = $iter->() ) { ... }

      This approach will put $iter in a tight scope and properly destroy.

      Needless to say, if Perl had macros like Lisp, we wouldn't need to repeat that discussion again and again...

      Keyword-simple could solve this, but is restricted to statements only.

      see also

      Can I check if a loop's scope is entered for the first time?

      Cheers Rolf
      (addicted to the 𐍀𐌴𐍂𐌻 Programming Language :)
      Wikisyntax for the Monastery

        I agree there are some edge cases to consider depending on the use-case...

        Code that fails subtly when an exceptions or next/last is occurs? It's not a question of if it's going to bite you, but when.

Re^6: Using lazy list with a for loop
by Anonymous Monk on Jan 03, 2023 at 04:16 UTC
    hence you need to switch to while and add an iterator method ->each to your API °
    while (my ($widget) = $api->each( $item->{sets}{widgets})) { ... }
    That would now be the ideal for me, but don't you need to instantiate the iterator before calling it? Like:
    my $iter = $api->each( $item->{sets}{widgets} ); while (my ($widget) = $iter->()) { ... }
    I wonder if you can combine the intializer with the iterator in a single call and have it rebless itself on the first call. Algorithm::Combinatorics does something similar.
      depending on your use cases, yes.

      for instance you could bind the iterator to the code-line where it is first invoked like available via caller

      the next question is if the iterator needs to be destroyed because you leave the loop via last. otherwise an inner loop wouldn't notice if it is reentered.

      For instance, an (IMHO extreme) requirement would be to properly support redo

      In order to cover all use cases you would need

      for (my $iter = create(...); my ($value) = $iter->get(); $iter->inc() +) { ...BODY... }

      as I said, not easy.

      Cheers Rolf
      (addicted to the 𐍀𐌴𐍂𐌻 Programming Language :)
      Wikisyntax for the Monastery