XP is just a number PerlMonks

### recursive /eg fails

by I0 (Priest)
 on Mar 27, 2002 at 02:49 UTC Need Help??
I0 has asked for the wisdom of the Perl Monks concerning the following question:

#
# I've striped down the core dump example, # It no longer core dumps under v5.6.1 but it still returns the wrong +answer # Can anyone explain why /C(2)/ is not getting substituted? use strict; print doFunc( "MAIN", "B(1)+C(2)" ); sub doFunc{ my \$theFunc = shift; local \$_ = shift; my \$re; \$re = \${{ "B(1)+C(2)" => '1|2', }}{\$_}||quotemeta; print "\$theFunc: '\$_'=~/\$re/\n"; print join"\n",/(\w+)\((\$re)\)/g,"\n"; \$_ =~ s/(\w+)\((\$re)\)/&doFunc(\$1,\$2)/eg; # /ego works /eg fails return "func \$theFunc returns <\$_>"; } #should return #func MAIN returns <func B returns <1>+func C returns <2>> #

Replies are listed 'Best First'.
Re: recursive /eg fails
by stephen (Priest) on Mar 27, 2002 at 09:15 UTC

Tricky... I hate to risk crying wolf, but there may be a Perl bug going on here.

I'm assuming that this is the beginning stage of a japh?

Although I haven't solved the problem, I'm posting a slightly more untangled version of the code (think of it as a preemptive deobfuscation) in order to make the problem a bit clearer.

On perl 5.6.1 on Linux, this code returns "func MAIN returns func B returns 1+C(2)", when by intuition it should return "func MAIN returns func B returns 1+2". On perl 5.6.1 on Windows, the program coredumps.

use strict; print doFunc( "MAIN", "B(1)+C(2)" ); sub doFunc{ my (\$theFunc, \$rem) = @_; my \$re = &get_re(\$rem); \$rem =~ s/(\w+)\((\$re)\)/&doFunc(\$1,\$2)/eg; return "func \$theFunc returns \$rem"; } ## ## When we're called with the initial ## state, return "1|2". Otherwise, return ## our input, quotemeta'd. ## sub get_re { my (\$in) = @_; if (\$in eq "B(1)+C(2)") { return '1|2'; } else { return quotemeta(\$in); } }

stephen

Re: recursive /eg fails
by derby (Abbot) on Mar 27, 2002 at 13:03 UTC
I0,

You have no base clase case for your recursion. When you get down to the bottom call, you try to execute "func xxx returns y". Try this (tip to stephen for cleaning it up):

#!/usr/bin/perl -wd use strict; print doFunc( "MAIN", "B(1)+C(2)" ); sub doFunc{ my (\$theFunc, \$rem) = @_; my \$re = &get_re(\$rem); if( \$rem ne \$re ) { \$rem =~ s/(\w+)\((\$re)\)/doFunc(\$1,\$2)/eg; } return "func \$theFunc rets \$rem"; } ## ## When we're called with the initial ## state, return "1|2". Otherwise, return ## our input, quotemeta'd. ## sub get_re { my (\$in) = @_; if (\$in eq "B(1)+C(2)") { return '1|2'; } else { return quotemeta(\$in); } }

-derby

update: There's a base case and a base class (no relation) but base clase?

update: Just spent a few minutes with your original. Here's it is with the base case added:

print doFunc( "MAIN", "B(1)+C(2)" ); sub doFunc{ my \$theFunc = shift; local \$_ = shift; my \$re; \$re = \${{ "B(1)+C(2)" => '1|2', }}{\$_}||quotemeta; print "\$theFunc: '\$_'=~/\$re/\n"; print join"\n",/(\w+)\((\$re)\)/g,"\n"; if( \$_ ne \$re ) { \$_ =~ s/(\w+)\((\$re)\)/&doFunc(\$1,\$2)/eg; # /ego works /eg fails } return "func \$theFunc returns <\$_>"; }
Re: recursive /eg fails
by flocto (Pilgrim) on Mar 27, 2002 at 14:39 UTC
I played around with your code (well, actually I used Stephens's code for simplicity) and found a solution that amazed me: If you add 'o' to the regex operators (making it '/ego') everything works as expected. Here's my code:
#!/usr/bin/perl -w use strict; print doFunc("MAIN", "B(1)+C(2)") . "\n"; sub doFunc { my (\$theFunc, \$rem) = @_; my \$re = &get_re(\$rem); \$rem =~ s/(\w+)\((\$re)\)/&doFunc(\$1,\$2)/eog; return "func \$theFunc returns <\$rem>"; } ## ### When we're called with the initial ### state, return "1|2". Otherwise, return ### our input, quotemeta'd. ### sub get_re { my (\$in) = @_; if (\$in eq "B(1)+C(2)") { return '1|2'; } else { return quotemeta (\$in); } } exit (0);
Sorry that I can't tell you why perl is behaving like this. '/o' shouldn't change the behavior at all (at least that's what I though) and \$re doesn't change either.. Maybe perl messes up the namespaces when doing recursive calls using a regex? I really don't know..

By the way: When I'm not using the '/o' operator and trying to print to STDERR just before the regex is executed my perl (5.6.1, linux 2.4.2) coredumps on me..

Regards, -octo-
Re: recursive /eg fails
by Anonymous Monk on Mar 27, 2002 at 03:45 UTC
yeah, I can't read that sorry.

What does

\$re = \${{ "B(1)+C(2)" => '1|2', }}{\$_}||quotemeta;
do? (I know what the code says, but as to why anyone'd write this is beyond me, it's not useful). what I would do is compile \$re so it is a regex, using qr (see perlop).

Also, it will never print func MAIN ,
first it will print MAIN: 'B(1)+C(2)'=~/....

Adding \$re = qr/\$re/; has the same problem.

Create A New User
Node Status?
node history
Node Type: perlquestion [id://154569]
Approved by root
help
Chatterbox?
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others chilling in the Monastery: (7)
As of 2018-02-20 17:46 GMT
Sections?
Information?
Find Nodes?
Leftovers?
Voting Booth?
When it is dark outside I am happiest to see ...

Results (273 votes). Check out past polls.

Notices?