in reply to Porting tqdm to Perl

The typical approach in Perl would be a while loop...

my $it = tqdm(100); while (my $i = $it->next) { ... }

Plenty of variations are possible, for example, $it doesn't need to be an object, it could just be a code ref; or, if it is an object, it can overload the <> operator (while(<$it>)), etc.

BTW, Higher-Order Perl is great for this kind of stuff.

Update: One advantage of overloading <> is that a while(<$it>) is automatically translated to while (defined($_ = readline $it)), meaning that only undef terminates the sequence, and not other false values like 0:

use warnings; use strict; { package Iterator; use overload '<>' => sub { my $self = shift; if (wantarray) { my @all; while (defined( my $x = $self->() )) { push @all, $x } return @all; } else { return $self->() } }; sub new { my $class = shift; my @values = @_; my $i=0; return bless sub { if ($i>=@values) { $i=0; return } return $values[$i++]; }, $class; } } use Test::More tests=>2; my $it1 = Iterator->new(-5..5); my @o1; while (<$it1>) { push @o1, $_; } is_deeply \@o1, [-5,-4,-3,-2,-1,0,1,2,3,4,5]; SKIP: { skip "need Perl >= v5.18 for overloaded <> in list context", 1 unless $] ge '5.018'; # [perl #47119] my $it2 = Iterator->new(-5..5); is_deeply [<$it2>], [-5,-4,-3,-2,-1,0,1,2,3,4,5]; }

Replies are listed 'Best First'.
Re^2: Porting tqdm to Perl (updated)
by perlancar (Hermit) on Dec 21, 2018 at 13:58 UTC

    Yes, creating an iterator (either a full object or just a coderef) would be one of the obvious choices. Overloading the diamond operator is interesting, thanks for pointing that out. Sadly, all these are still far from the "just add 4+2 characters to do progress bar" that the Python's tqdm libary enables.

    As someone wrote in How to Write Perfect Python Command-line Interfaces — Learn by Example: "Do you see any difference? It is not so easy to spot because the difference consists of 4 letters: TQDM. (...) This is the name of a Python library and this is the name of its unique class, with which you wrap any iterable to print the corresponding progression. (...) And this results in a beautiful progress bar. Personally, I still find it too good to be true."

    It's seldom that I feel Python envy, but this is one of those moments :-)