use v5.14; use strict; use warnings qw(all); BEGIN { package More::For; use Carp; use Exporter::Shiny our @EXPORT = qw(more); use PadWalker (); use Parse::Keyword { more => \&_parse_more }; use Scope::Upper qw( localize UP ); sub _parse_more { my $tmpvar = '@More::For::____list_' . do { state $cnt = 0; ++$cnt }; lex_read_space; lex_peek(7) eq 'foreach' ? lex_read(7) : lex_peek(3) eq 'for' ? lex_read(3) : croak("Expected opening parenthesis"); lex_read_space; lex_peek eq '(' ? lex_read(1) : croak("Expected opening parenthesis"); lex_read_space; my $list = parse_fullexpr; lex_read_space; lex_peek eq ')' ? lex_read(1) : croak("Expected closing parenthesis"); lex_read_space; lex_peek(2) eq 'as' ? lex_read(2) : croak("Expected 'as'"); lex_read_space; my $vars = ''; while (lex_peek ne '{') { $vars .= lex_peek(1); lex_read(1); } my $count_vars = split /\,/, $vars; lex_read(1); lex_stuff( sprintf( 'while (%s = splice(%s, 0, %d)) {', $vars, $tmpvar, $count_vars, ), ); return (sub { $tmpvar, $list }, 1); } sub more { my ($tmpvar, $list) = @_; # Fix Parse::Keyword's handling of closed over variables my $peek_my; my %closed_over = %{PadWalker::closed_over($list)}; for my $var (keys %closed_over) { $peek_my //= PadWalker::peek_my(1); $closed_over{$var} = $peek_my->{$var}; } PadWalker::set_closed_over($list, \%closed_over); localize($tmpvar, [$list->()], UP); } }; package main; use More::For; my $x = 1; my $y = 9; more for ( $x .. $y ) as ( my($a), our($b), my $c ) { say join(":", $a, $main::b, $c); } say "done";