Beefy Boxes and Bandwidth Generously Provided by pair Networks
Don't ask to ask, just ask
 
PerlMonks  

Shot myself in the foot with a pos

by Guildenstern (Deacon)
on Aug 10, 2000 at 18:22 UTC ( [id://27292]=perlmeditation: print w/replies, xml ) Need Help??

Well, I certainly am glad I just picked up the new Camel book. I had been having quite a time trying to find patterns common to multiple strings. I had sample input of two strings "ABCD". For each 1,2,3 and 4 character substring there should have been 2 matches, right? Not so. My original code looked liked this (relevant part only):
$all{$str} += $packets[$_] =~ /$str/g;
When I ran it against the sample input, I got weird output. For example, two character substring matches:
  • AB - 2 matches (good!)
  • BC - 0 matches (eh?)
  • CD - 2 matches (good again!)
Any combination would produce the weird 2,0,2,0, etc pattern of matching.
Following much frenzied thumbing through the Camel, I ran across almost an offhand mention to pos. I added the line
pos $_ = 0; after the previous line, and now the counts work perfectly.
I feel good that I managed to find this one by reading the FM, but also feel that I should mention it since it never came up in any of the (wonderful!) responses I've received to the pattern matching problem and its revisit.

Replies are listed 'Best First'.
RE: Shot myself in the foot with a pos
by tilly (Archbishop) on Aug 10, 2000 at 19:41 UTC
    A simpler solution is to lose the /g on your match:
    if ($packets[$i] =~ /$str/g) { ++$all{$str}; }
    Also note that the rewrite means people don't have to remember relative precedence - always a good thing IMO.

    BTW I am curious whether you ever tried out what I offered at One possible answer. It is a rather different idea than the other solutions you were given, and I wouldn't mind knowing how it works in practice. (It could be very slow and use a lot of memory, it might be fast, I really don't know have a good sense of how it will scale.)

      I think it's a bad idea to let readers off the hook when it comes to any language rules, including precedence rules. The whole language is there for me to use when appropriate, and I'm not going to take very well to instructions to back off some construct just because it takes a little research to understand the first time.

          -- Chip Salzenberg, Free-Floating Agent of Chaos

        I think if I took that attitude when I started at my current job I wouldn't have wound up being asked to train most of the other programmers how to use Perl.

        I wholeheartedly agree that any good Perl programmer should know the precedence rules. That does not mean that their code should be written using them all if you have any expectation that it will someday have to be altered by someone not as conversant as you.

        But this is a disagreement we won't settle any time soon. One of my sillier mistakes was to have this argument with Tom C. You know that I deliberately limit myself to a set of constructs that I think I can teach to others. The one I was responding to is simply not common enough for me to want it on a short-list of things I have to teach. OTOH another time I showed a construct I had to deal with (that was written by someone else) to p5p and got general shock and horror about how convoluted it was. Plus one of my favorite quotes ever on programming from Tom C:

        A programmer who hasn't been exposed to all four of the imperative, functional, objective, and logical programming styles has one or more conceptual blindspots. It's like knowing how to boil but not fry. Programming is not a skill one develops in five easy lessons.

        I think that when there are valid and valuable constructs that can cause that much reaction on a list with as many tuits as p5p, it is beyond the bounds of reason to expect most companies to have people who could maintain a code-base that uses all of them.

        For bystanders, the construct handed to me is this:

        print join ",", map { &{$field_info{$_}{format}}($deal) } @fields;
        I pointed out that I had cleaned it up. Thanks to merlyn it got cleaned up a bit more, and this construct shows up from time to time in my code like this:
        my @field_subs = map {$field_info{$_}{format}} @fields; # TIME PASSES print join ",", map {$_->($deal)} @field_subs;
        In fact a variation of it appeared in my first post here, at A few style suggestions.
      did you mean
      if ($packets[$i] =~ /$str/) {?
      The only thing that I see with this is if there's multiple instances of $str in $packets$i, the hash counter won't be incremented correctly. If I leave the /g in, my matches won't happen because pos is past the start of a match.
      For example, I have ABC and I check (and match the substring AB). This means that pos points at C now. If I go through again and try to match the substring BC, it won't find it.
      Maybe I've misunderstood what you were suggesting here. Correct me if necessary.

      As far as the solution you provided, I haven't tried it yet. To be completely honest, I'm just trying to get myself into the groove of learning the minor nuances of Perl, and I have very little idea of what parts of your code are doing. Fear not, though - I am going through it bit by bit with my Camel book at hand, and hopefully in the next day or two I'll feel confident enough to run it. I'd like to at least be able to tweak things if I need to and know what I'm doing! :)
        Perl only cares about pos() for matches with the /g modifier. Drop the /g, and all attempts at matching start from the beginning of the string.

        As for the code I provided, well good luck deciphering it. The algorithm I used is pretty complex. The key idea though is for each packet to maintain a hash whose keys are the substrings we are still interested in, and whose values are the set of positions in that packet where the pattern starts. :-)

        I don't tend to write production code like that....

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others making s'mores by the fire in the courtyard of the Monastery: (5)
As of 2024-04-26 09:13 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found