http://qs321.pair.com?node_id=1232663


in reply to Re^4: Getting for() to accept a tied array in one statement
in thread Getting for() to accept a tied array in one statement

Try this:

sub wrapper : lvalue { tie my @x, "MyClass", @_; @x; } for( wrapper("first", "second") ) { print "In loop = "; print "$_\n"; }

As I said initially I am not expert in this, so there might be undesired side effects...

And FETCHSIZE is called once only...

Replies are listed 'Best First'.
Re^6: Getting for() to accept a tied array in one statement
by perlancar (Hermit) on Apr 16, 2019 at 14:23 UTC

    hdb, you're my hero :-) My faith in Perl is restored again.

      Why do you want to make something so simple so complicated and expensive? Use an iterator!

      sub make_list_iterator { my @list = @_; return sub { return () if !@list; return shift(@list); }; } my $iter = make_list_iter("some", "el", "ems"); while ( my ($item) = $iter->() ) { ... }

      As a bonus, one doesn't need to know the length of the list in advance with an iterator!

        I believe (or at least this is how I understand it) that the point of the exercise is SoC. The 'wrapper' causes a separate function to execute every time an element inside of the array is accessed and this function is defined somewhere else (not inside the while loop). Your code could work in case it would have used a reference array instead. But I think you mean with 'expensive' you mean using the tie?

        Anyways, if you would use an array reference your code does work:

        use lib '.' ; use strict ; use warnings ; use ar ; my @ar ; my $ar2 = tie @ar, "ar" ; @ar = (1, 2, 3) ; sub make_list_iterator { my $list = $_[0] ; return sub { return () if !@{$list}; return shift(@{$list}); }; } my $iter = make_list_iterator(\@ar) ; while ( my ($item) = $iter->() ) { print "$item\n" ; }

        I'm not showing how to implement ar, plenty of examples in previous posts

        Yes, the goal is not finding out the best way to do a progress-bar API (I think doing the Progress::Any-style progress bar is still okay), but how to emulate the style of a Python library.

        As a bonus, one doesn't need to know the length of the list in advance with an iterator!

        With for(@tied_array) we also doesn't need to calculate the length of the list in advance. We can just retrieve an item one by one, and for() will still invoke FETCHSIZE on each iteration. Which incurs an extra cost, admittedly.