How to use (??{code}) correctly in foreach loop?


P

Peng Yu

Hi,

I have the following code and output. I'm not sure why the code
doesn't search for 'abc' in the second string 'efgabcabcd'. Could you
anybody let me know what the problem is and how to fix it?

$ cat main.pl
#!/usr/bin/env perl

use strict;
use warnings;

my @strings=('abcdefgabc', 'efgabcabcd');
my $pattern='abc';

foreach my $s (@strings) {
my @offsets=();
{
use re 'eval';
$s =~ /(?=\Q$pattern\E)(??{push @offsets, $-[0]})/g;
}
print join('::', @offsets), "\n"
}
print "end\n";

$ ./main.pl
0::7

end
 
Ad

Advertisements

I

Ilya Zakharevich

Hi,

I have the following code and output. I'm not sure why the code
doesn't search for 'abc' in the second string 'efgabcabcd'. Could you
anybody let me know what the problem is and how to fix it?

$ cat main.pl
#!/usr/bin/env perl

use strict;
use warnings;

my @strings=('abcdefgabc', 'efgabcabcd');
my $pattern='abc';

foreach my $s (@strings) {
my @offsets=();
{
use re 'eval';
$s =~ /(?=\Q$pattern\E)(??{push @offsets, $-[0]})/g;
}
print join('::', @offsets), "\n"
}
print "end\n";

I have no idea what do you want to achieve. Do you think it is a
scalar context //g, or a list content?

Anyway, I suspect a bug in scalar/list context //g applied to a
foreach-iterator. Did you try it without (??{}) ?

Ilya
 
G

George Mpouras

Peng Yu said:
Hi,

I have the following code and output. I'm not sure why the code
doesn't search for 'abc' in the second string 'efgabcabcd'. Could you
anybody let me know what the problem is and how to fix it?

$ cat main.pl
#!/usr/bin/env perl

use strict;
use warnings;

my @strings=('abcdefgabc', 'efgabcabcd');
my $pattern='abc';

foreach my $s (@strings) {
my @offsets=();
{
use re 'eval';
$s =~ /(?=\Q$pattern\E)(??{push @offsets, $-[0]})/g;
}
print join('::', @offsets), "\n"
}
print "end\n";

$ ./main.pl
0::7

end



# Here is what you want
# somehow the (??{[email protected]}) defines the arrray as local at the
namespace at first time
# and "my" undefine it or something like that !

use strict;
use warnings;

my @strings=('abcdefgabc', 'efgabcabcd');
my $pattern='abc';
my @offsets=();

use re 'eval';
foreach my $s (@strings)
{
$s =~ /(?=\Q$pattern\E)(??{push @offsets, $-[0]})/g;
print "Offsets of $s: @offsets\n"
}
no re;

print "end\n";
 
G

George Mpouras

# sorry here is the correct one !

use strict;
use warnings;

my @strings=('abcdefgabc', 'efgabcabcd');
my $pattern='abc';
my @offsets=();

foreach my $s (@strings)
{
@offsets=();
{use re 'eval'; $s =~ /(?=\Q$pattern\E)(??{push @offsets, $-[0]})/g }
print "Offsets of $s: @offsets\n"
}

print "end\n";
 
P

Peng Yu

# sorry here is the correct one !

use strict;
use warnings;

my @strings=('abcdefgabc', 'efgabcabcd');
my $pattern='abc';
my @offsets=();

foreach my $s (@strings)
{
@offsets=();
{use re 'eval'; $s =~ /(?=\Q$pattern\E)(??{push @offsets, $-[0]})/g }
print "Offsets of $s: @offsets\n"

}

print "end\n";

This works. Thank you!

Also, I don't quite understand why "my @offsets;" has to be moved out
of the loop.

I checked Programming Perl 3rd edition. There are thousands of "my" in
this book. Would you please help me understand why it is the case by
pointing me which page of Programming Perl or which perl document (and
what part of it) I should read?
 
G

George Mpouras

Also, I don't quite understand why "my @offsets;" has to be moved out of
There is nothing wrong with your code . It looks like a bug to me .
(??{[email protected] ...}) } somehow defines the array as global at first time ,
and "my" seems to overide this definition
 
Ad

Advertisements

I

Ilya Zakharevich

my @offsets=();

foreach my $s (@strings)
{
@offsets=();
{use re 'eval'; $s =~ /(?=\Q$pattern\E)(??{push @offsets, $-[0]})/g }
print "Offsets of $s: @offsets\n"

}
This works. Thank you!
Also, I don't quite understand why "my @offsets;" has to be moved out
of the loop.

This one is new to me...

When I first implemented (??{}), I did not cover one case in
"dynamically create new chunk of compile tree" logic. This lead to
bugs when (??{}) accesses lexicals in recursive subroutines. (Not
hard to fix, but, apparently, nobody did it...)

Now you say that there is also a problem with accessing lexicals
defined inside a loop? Strange... Probably, the logic of the first
loop may be as in:

A lexical @array is created;

REx is compiled; the compile tree contains a reference to the @array;

On exit from the loop the garbage collector of lexicals checks the
refcount of @array; it is now 1 more than expected, so it thinks an
EXTERNAL reference to the array exists, and "renews" @array;

On following iterations "there is no visible need" to renew @array
and recompile the REx, so none of these steps happens. However, on
these iterations @array visible from Perl code and @array visible from
inside (??{}) are different containers.

Hope this helps,
Ilya
 
Ad

Advertisements

C

C.DeRykus

Hi,

I have the following code and output. I'm not sure why the code
doesn't search for 'abc' in the second string 'efgabcabcd'. Could you
anybody let me know what the problem is and how to fix it?

$ cat main.pl
#!/usr/bin/env perl

use strict;
use warnings;

my @strings=('abcdefgabc', 'efgabcabcd');
my $pattern='abc';

foreach my $s (@strings) {
  my @offsets=();
  {
    use re 'eval';
    $s =~ /(?=\Q$pattern\E)(??{push @offsets, $-[0]})/g;
  }
  print join('::', @offsets), "\n"}

print "end\n";

$ ./main.pl
0::7

end

Is there some reason you need to use (?{{...})
which is tagged 'experimental' ...

A simple alternative, eg:

my $regex = qr/abc/;
foreach my $s (@strings) {
push @offsets,$-[0] while $s =~ /$regex/g;
}
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top