Beefy Boxes and Bandwidth Generously Provided by pair Networks
The stupid question is the question not asked
 
PerlMonks  

RFC: Accelerated stepping

by hexcoder (Deacon)
on Sep 01, 2008 at 22:04 UTC ( #708339=perlmeditation: print w/replies, xml ) Need Help??

Dear monks,

often when I debug functional style programs (that is there are some greps and maps present), then I wished for some accelerated stepping in the debugger.

Example:
Instead of

main::(perldb_demo.pl:4): my @a = (1..10); DB<1> n main::(perldb_demo.pl:6): if (0 < scalar grep { $_ == 9 } @a) { DB<1> main::(perldb_demo.pl:6): if (0 < scalar grep { $_ == 9 } @a) { DB<1> main::(perldb_demo.pl:6): if (0 < scalar grep { $_ == 9 } @a) { DB<1> main::(perldb_demo.pl:6): if (0 < scalar grep { $_ == 9 } @a) { DB<1> main::(perldb_demo.pl:6): if (0 < scalar grep { $_ == 9 } @a) { DB<1> main::(perldb_demo.pl:6): if (0 < scalar grep { $_ == 9 } @a) { DB<1> main::(perldb_demo.pl:6): if (0 < scalar grep { $_ == 9 } @a) { DB<1> main::(perldb_demo.pl:6): if (0 < scalar grep { $_ == 9 } @a) { DB<1> main::(perldb_demo.pl:6): if (0 < scalar grep { $_ == 9 } @a) { DB<1> main::(perldb_demo.pl:6): if (0 < scalar grep { $_ == 9 } @a) { DB<1> main::(perldb_demo.pl:6): if (0 < scalar grep { $_ == 9 } @a) { DB<1> main::(perldb_demo.pl:7): print "found\n";

I would like to have
main::(perldb_demo.pl:4): my @a = (1..10); DB<1> n main::(perldb_demo.pl:6): if (0 < scalar grep { $_ == 9 } @a) { DB<1> main::(perldb_demo.pl:7): print "found\n";

So generally I would like to use the debugger command 's' for small steps/increments and 'n' for bigger steps. In the example above, if the original behavior is wanted, use the 's' command which still interrupts grep's code block for each element.

I asked Richard Foley about it, and he agreed that this might be useful for other users as well. Also, modifying the 'n' command would make more sense than to add a new command just for stepping over grep/map/sort and otherwise being identical to 'n'.
A possible danger of this change might be this: the actual involved looping is not visible anymore, leading to a false impression of efficiency.

So, I have made a patch for the debugger (Perl 5.10.0). Currently the new code checks for grep/map/sort and in that case sets a temporary breakpoint like the 'c' command would do. Otherwise the old behavior is used. Probably other operators (all, any, ...) from List::Util and List::MoreUtils would qualify also, but currently they are not part of the core.

Before I contact p5p, I would like to hear your opinions for this proposal.

Thanks for comments!

--- perl5db.pl.org 2007-12-18 10:47:07.000000000 +0100 +++ perl5db.pl 2008-09-01 23:02:16.718750000 +0200 @@ -2643,7 +2643,7 @@ demarcation' above which commands can be entered anytime, and below w +hich they can't. -=head4 C<n> - single step, but don't trace down into subs +=head4 C<n> - single step, but don't trace down into subs, and not ev +en into grep/map/sort Done by setting C<$single> to 2, which forces subs to execute straigh +t through when entered (see C<DB::sub>). We also save the C<n> command in C<$la +ststep>, @@ -2655,9 +2655,41 @@ $cmd =~ /^n$/ && do { end_report(), next CMD if $finished and $level <= + 1; - # Single step, but don't enter subs. - $single = 2; + if ( $dbline[$line] =~ m{\b( + grep + | + map + | + sort)\b}xms + ) { + # Scan forward to the next executable lin +e + $i = $line; + ++$i; + $max = $#dbline; + ++$i while $dbline[$i] == 0 && $i < $max; + # Check if we would leave the sub + my @sublast = split m{-}xms, $sub{$sub}; + if (($sub eq '' || $i <= $sublast[-1]) + && $dbline[$i] != 0) { + # Next line is in current sub + # or no sub at all + + # Set up the one-time-break sigil. + $dbline{$i} =~ s/($|\0)/;9$1/; # add + one-time-only b.p. + + # Clear single stepping flags + $DB::single &= ~3; + } else { + # have no line (oneliner) + # or about to leave the sub... + # Turn on stack tracing one level up. + $stack[ -1 ] |= 1; + } + } else { + # Single step, but don't enter subs. + $single = 2; + } # Save for empty command (repeat last). $laststep = $cmd; last CMD;

Replies are listed 'Best First'.
Re: RFC: Accelerated stepping
by FunkyMonk (Chancellor) on Sep 01, 2008 at 22:19 UTC
    ++ for just this simple text...
    's' for small steps/increments and 'n' for bigger steps
    I use the debugger a lot but I always confuse 's' and 'n' (I like to think in terms of 'Step into' and 'Step over', which doesn't help). Earlier today I was trying to think of a mnemonic I could use, and failed.

    's' = 'small step' works for me. So thanks for that

Re: RFC: Accelerated stepping
by grinder (Bishop) on Sep 02, 2008 at 13:15 UTC

    I think it's great to see people daring to dive into the unplumbed depths of perl5db.pl. Few who have ventured there remained sane enough to describe their experiences afterwards.

    I think the likely response from p5p will to that you cannot change the behaviour of n for backwards compatibility reasons. The fact that you can no longer step through the innards of a map or grep is too much of loss. That said, I think the concept has great merit. To that end, an approach that is more likely to succeed would be to introduce a new command letter. N is currently free (according to my copy of bleadperl).

    As a minor stylistic issue, the Perl core hasn't drunk the PBP kool-aid, and thus you would probably want to write your check as the more compact

    if ($dbline[$line] =~ /\b(?:grep|map|sort)\b/) {...

    You also don't need to capture it. I also wonder if that will pick up a "map" in a quoted string or a comment...

    In a similar vein, I think my @sublast = split m{-}xms, $sub{$sub} looks slightly silly.

    split /-/ is fine.

    update: I am a bit thick sometimes. It took tye's reply for me to realise that there is no loss of functionality. So the N hack isn't necessary. So what's left is purely a matter of code style.

    • another intruder with the mooring in the heart of the Perl

      Thanks,

      Actually I first thought of introducing a new 'N' or even 'nn' command, but I then considered the difference to 'n' too miniscule to bother with it.

      The fact that you can no longer step through the innards of a map or grep is too much of loss.

      It is possible, if you use 's'.

      Regarding the coding style, yes, when in Rome, talk like romans do, so when in Perl4 code talk like Perl4 coders did :-).
      BTW: is perl5db.pl required to be backward compatible to Perl 4.x??

        I then considered the difference to 'n' too miniscule to bother with it.

        Others won't.

        is perl5db.pl required to be backward compatible to Perl 4.x

        Well of course not. It uses lexical variables for starters. You are looking at possibly the oldest, continually tweaked file in the Perl distribution though. It has enough cruft and differing code styles and idioms without adding one more.

        • another intruder with the mooring in the heart of the Perl

Re: RFC: Accelerated stepping
by alexm (Chaplain) on Sep 02, 2008 at 22:25 UTC
    Before I contact p5p, I would like to hear your opinions for this proposal.

    From time to time, I wonder why n doesn't jump map, grep, etc. I usually end up using c in those cases, but it's slower since I need to get the line number first. Therefore, I suggest that you try p5p, explain them grinder's comments about backwards compatibility and the idea of using N as an alternative.

    BTW, maybe if it was possible to set n as an alias for N and let people decide whatever they like most would be the perfect solution. However, I'm not sure that aliasing (or redefining) commands is possible at all.

      From time to time, I wonder why n doesn't jump map, grep, etc.

      Everytime a code block is entered, the Perl core delivers control to the debugger. Now it seems to me, when 'n' was created, some additional logic has been implemented, in order to shortcut the execution of subroutines, but not code blocks (like from map/grep/sort) in general.
      So I could even file a bug report :-)). That depends on your viewpoint, of course.

      Update: I think the patch could be made better, if the general problem of shortcutting code blocks is solved. Then also operators (any, all, ...) from List::Utils and friends could be stepped over. So, I will look into it again. Stay tuned...

      Therefore, I suggest that you try p5p, explain them grinder's comments about backwards compatibility and the idea of using N as an alternative.

      That is a great suggestion, thanks. I will ask them how serious they value backward compatibility in this case. Either it can be changed, or there will be a new command then.

      I will also try out, if the '=' alias can be used to redefine 'n'.

      Finally, the 'Perl Hacks' book has hack #59 for writing your own debugger commands or modifying existing ones. But since many (most?) users want the change, it might be better to change it once in the debugger source.

        Oh, I think it's a good idea to change the source. In terms of backward compatibility you've still got 's' (step into), while the 'n' (next statement) is always a pain when 'n'-ing over sort and map blocks. Of course you can 'c' (continue) to a new location (line), but then you have to stop, break your flow, and work out where you want to go specifically. It's nice to see someone prepared to delve into those murky depths to fix this behaviour to be more intuitive at last. R.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlmeditation [id://708339]
Approved by GrandFather
Front-paged by GrandFather
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others taking refuge in the Monastery: (1)
As of 2022-07-07 02:19 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found

    Notices?