in reply to Re^2: Refactoring challenge.
in thread Refactoring challenge.

Honestly, I did think of doing it that way, but considered it rather too repetitive. The problem is there are conditions under which you want to change the depth for your next state — but a separate issue is whether you want to change depth before processing the current state. That's why the code ends up so messy.

The following doesn't get rid of the variable, but rather repurposes and renames it to separate the two distinct decisions involved more cleanly.

{ my( $indent, $depth ) = ( "\t", 0 ); sub pp { my $next_depth; my( $end_chunk, $first ) = f1( $str ); if( defined $first ) { if( $first eq CONST1 ) { ++$end_chunk; $next_depth = --$depth; } elsif( defined my $pos2 = f2( $str, $first ) ) { $next_depth = $depth; $end_chunk = $pos2 + 2; } else { $next_depth = $depth + 1; } } else { $next_depth = $depth; } print $indent x $depth, substr( $str, 0, $end_chunk ); $str =~ s[^.{$end_chunk}\s*][]; $depth = $new_depth; return; } }

I still think your code is doing a lot of manual pattern matching which could be better done by the regex engine.

Makeshifts last the longest.

Replies are listed 'Best First'.
Re^4: Refactoring challenge.
by BrowserUk (Patriarch) on Mar 07, 2005 at 16:20 UTC
    I still think your code is doing a lot of manual pattern matching which could be better done by the regex engine.

    By that, I assume you mean the indexBal() routine.

    If you can encapsulate this into a more efficient, or more simple routine by using the regex engine, please do, it would help me a lot. I tried and failed.

    sub indexBal { my( $string, $lookFor, $limit ) = @_; my $nesting = 0; for( my( $position, $char ) = ( 0, substr $string, 0, 1 ); $position < min( length( $string ) , $limit ); $char = substr $string, ++$position, 1 ) { $nesting++ if $char =~ m/[\[\{]/; $nesting-- if $char =~ m/[\]\}]/; die 'Unbalanced' if $nesting < 0; return $position if $char eq $lookFor and $nesting == 0 } return; } my $s = '{ [ { [ { x }, { y } ], [ z ] } ] } { [ { '; my $pos = indexBal $s, '}', length( $s ); print substr $s, 0, $pos+1; { [ { [ { x }, { y } ], [ z ] } ] }

    Note that:

  • The brackets and braces may be nested to any arbitrary depth.
  • The requested match may not yet be available.
  • There will nearly always be an incomplete set of nested brackets on the end of the string.
  • The routine takes a parameter that specifies the maximum length in which the match must be found else don't bother looking any further.

    Examine what is said, not who speaks.
    Silence betokens consent.
    Love the truth but pardon error.
      From browsing PM, seems like you a good place to be using Text::Balanced or maybe Parse::Recdesent. Unfortunately I'm still learning how to do this myself, so I can't help with the code.
        a good place to be using Text::Balanced or maybe Parse::Recdesent.

        Not really. You see, besides that they will only really work on a complete strings, not a partial string as here, they are so slow in use, cumbersome to learn to use, and so difficult to debug with, that I wouldn't recommend them to anyone, never mind use them myself.


        Examine what is said, not who speaks.
        Silence betokens consent.
        Love the truth but pardon error.