Skip Menu |
Report information
Id: 122829
Status: resolved
Priority: 0/
Queue: perl5

Owner: Nobody
Requestors:
Cc:
AdminCc:

Operating System: (no value)
PatchStatus: (no value)
Severity: low
Type:
Perl Version: (no value)
Fixed In: (no value)



Subject: Flipflop under recursion
Download (untitled) / with headers
text/plain 1.2k
perlop.pod states: Each ".." operator maintains its own boolean state, even across calls to a subroutine that contains it. While that is true and well-known, what few know is that recursive calls to the containing subroutine do not share that boolean state with the outer call. What’s weirder is that each recursion level maintains its own state. So, for instance, if you have a function calling itself recursively to the fifth level, the flip-flop operator evaluated at that level will not use the same state again until that function is called to that level again. I haven’t come up with an example of this weird behaviour yet, but I’ll try to post something in the next day or two. My question is: Is this behaviour intentional? It doesn’t match my reading of the documentation. And I can’t think of any use for it short of obfuscation. I am inclined to think this is a bug. Further, I have found a discrepancy in this operator, in that it returns the same scalar each time when the enclosing sub is not called recursively, but a different scalar each time when the enclosing sub *is* called recursively. I was about to fix that discrepancy, when I realised that sharing the state between recursion levels would make the fix easier (the same change would fix both). -- Father Chrysostomos
CC: bugs-bitbucket [...] rt.perl.org
Subject: Re: [perl #122829] Flipflop under recursion
To: Perl 5 Porters <perl5-porters [...] perl.org>
From: Jan Dubois <jand [...] activestate.com>
Date: Mon, 22 Sep 2014 18:19:08 -0700
Download (untitled) / with headers
text/plain 558b
On Mon, Sep 22, 2014 at 6:13 PM, Father Chrysostomos <perlbug-followup@perl.org> wrote: Show quoted text
> I was about to fix that discrepancy, when I realised that sharing the state between recursion levels would make the fix easier (the same change would fix both).
I don't actually know how this works, but I assume the observed behavior is due to the state being kept in the pad. Does your fix for sharing the state still work for threaded interpreters, where each interpreter needs to keep separate state? So just hanging it of the opcode wouldn't work. Cheers, -Jan
RT-Send-CC: perl5-porters [...] perl.org
Download (untitled) / with headers
text/plain 771b
On Mon Sep 22 18:19:26 2014, jdb wrote: Show quoted text
> On Mon, Sep 22, 2014 at 6:13 PM, Father Chrysostomos > <perlbug-followup@perl.org> wrote:
> > I was about to fix that discrepancy, when I realised that sharing the > > state between recursion levels would make the fix easier (the same > > change would fix both).
> > I don't actually know how this works, but I assume the observed > behavior is due to the state being kept in the pad.
Your assumption is correct. Show quoted text
> Does your fix for > sharing the state still work for threaded interpreters, where each > interpreter needs to keep separate state? So just hanging it of the > opcode wouldn't work.
I was thinking of having the same SV in the recursive pads, just as we do for constants under threads. -- Father Chrysostomos
RT-Send-CC: perl5-porters [...] perl.org
Download (untitled) / with headers
text/plain 1.1k
On Mon Sep 22 18:26:08 2014, sprout wrote: Show quoted text
> On Mon Sep 22 18:19:26 2014, jdb wrote:
> > On Mon, Sep 22, 2014 at 6:13 PM, Father Chrysostomos > > <perlbug-followup@perl.org> wrote:
> > > I was about to fix that discrepancy, when I realised that sharing > > > the > > > state between recursion levels would make the fix easier (the same > > > change would fix both).
> > > > I don't actually know how this works, but I assume the observed > > behavior is due to the state being kept in the pad.
> > Your assumption is correct. >
> > Does your fix for > > sharing the state still work for threaded interpreters, where each > > interpreter needs to keep separate state? So just hanging it of the > > opcode wouldn't work.
> > I was thinking of having the same SV in the recursive pads, just as we > do for constants under threads.
And by making the pad code treat them like constants, I thought I could avoid special cases. But that would cause closures to share state, whereas currently they don’t, and that could have serious consequences for backward-compatibility. So it looks as though I have to special-case flip targets regardless. -- Father Chrysostomos
RT-Send-CC: perl5-porters [...] perl.org
Download (untitled) / with headers
text/plain 576b
On Mon Sep 22 18:13:16 2014, sprout wrote: Show quoted text
> Further, I have found a discrepancy in this operator, in that it > returns the same scalar each time when the enclosing sub is not called > recursively, but a different scalar each time when the enclosing sub > *is* called recursively. > > I was about to fix that discrepancy, when I realised that sharing the > state between recursion levels would make the fix easier (the same > change would fix both).
I went ahead and fixed that discrepancy in commit 14d91147b without touching the recursion issue. -- Father Chrysostomos
RT-Send-CC: perl5-porters [...] perl.org
Download (untitled) / with headers
text/plain 1.4k
On Mon Sep 22 18:13:16 2014, sprout wrote: Show quoted text
> perlop.pod states: > > Each ".." operator > maintains its own boolean state, even across calls to a subroutine > that contains it. > > While that is true and well-known, what few know is that recursive > calls to the containing subroutine do not share that boolean state > with the outer call. What’s weirder is that each recursion level > maintains its own state. So, for instance, if you have a function > calling itself recursively to the fifth level, the flip-flop operator > evaluated at that level will not use the same state again until that > function is called to that level again. > > I haven’t come up with an example of this weird behaviour yet, but > I’ll try to post something in the next day or two.
s/day/month/ :-) # This routine maintains multiple flip-flop states, each with its own # numeric ID, starting from 1. Pass the ID as the argument. sub f { my $depth = shift() - 1; return f($depth) if $depth; return /3/../5/; } for(1..20) { if (f(1)) { my $outer = $_; for(1..10){ print "$outer $_\n" if f(2); } } } The output is: 3 3 3 4 3 5 4 3 4 4 4 5 5 3 5 4 5 5 13 3 13 4 13 5 14 3 14 4 14 5 15 3 15 4 15 5 Now how much code is depending on that bug? None, I would imagine. And if someone wanted to write something like the above, an array of closures would be a more straightforward way to do it. After all, the higher the ID, the slower the flip-flop function. -- Father Chrysostomos
RT-Send-CC: perl5-porters [...] perl.org
Download (untitled) / with headers
text/plain 688b
On Mon Sep 22 18:13:16 2014, sprout wrote: Show quoted text
> perlop.pod states: > > Each ".." operator > maintains its own boolean state, even across calls to a subroutine > that contains it. > > While that is true and well-known, what few know is that recursive > calls to the containing subroutine do not share that boolean state > with the outer call. What’s weirder is that each recursion level > maintains its own state. So, for instance, if you have a function > calling itself recursively to the fifth level, the flip-flop operator > evaluated at that level will not use the same state again until that > function is called to that level again.
Fixed in 00e40766. -- Father Chrysostomos


This service is sponsored and maintained by Best Practical Solutions and runs on Perl.org infrastructure.

For issues related to this RT instance (aka "perlbug"), please contact perlbug-admin at perl.org