From robert.l.harris at gmail.com Tue Apr 19 13:28:26 2016 From: robert.l.harris at gmail.com (Robert L. Harris) Date: Tue, 19 Apr 2016 20:28:26 +0000 Subject: [Denver-pm] Dispatch Lists? Message-ID: Anyone have a straight forward script using dispatch lists? I have one ( 4500 lines by now ) which effectively does this: 1. Open input file 2. while { 3. $Line= 4. &Sub1("Line") if ( $Line =~ // ); 5. &Sub2("Line") if ( $Line =~ // ); 6. &Sub3("Line") if ( $Line =~ // ); 7. ... about 25 patterns now ... 8. } Yeah, it's ugly, it started out as a 30 line data munger about 2.5 years ago and I'm looking to speed and clean it up. Each Sub performs various actions based which can't be simplified or condensed more than they have. I've created my DispatchHash for subs/patterns but I think I'm confusing myself on actually doing the match and dispatch including passing $Line to the sub. Any examples would be very welcome. Robert -------------- next part -------------- An HTML attachment was scrubbed... URL: From saj at thecommune.net Tue Apr 19 16:17:01 2016 From: saj at thecommune.net (Stuart A Johnston) Date: Tue, 19 Apr 2016 17:17:01 -0600 Subject: [Denver-pm] Dispatch Lists? In-Reply-To: References: Message-ID: <5716BC6D.5060505@thecommune.net> Here's a simple example. I've just used $ARGV[0] as the input but you could add another loop for your multi-line input. #!/usr/bin/perl use strict; use v5.10; sub sub_foo { say "foo: $_[0]"; } sub sub_bar { say "bar: $_[0]"; } my @dispatch = ( [ qr/foo/, \&sub_foo ], [ qr/bar/, \&sub_bar ], ); foreach my $d (@dispatch) { my ($r, $sub) = @$d; if ($ARGV[0] =~ $r) { $sub->($ARGV[0]); next; } } On 04/19/2016 02:28 PM, Robert L. Harris wrote: > > Anyone have a straight forward script using dispatch lists? I have one > ( 4500 lines by now ) which effectively does this: > > 1. Open input file > 2. while { > 3. $Line= > 4. &Sub1("Line") if ( $Line =~ // ); > 5. &Sub2("Line") if ( $Line =~ // ); > 6. &Sub3("Line") if ( $Line =~ // ); > 7. ... about 25 patterns now ... > 8. } > > Yeah, it's ugly, it started out as a 30 line data munger about 2.5 years > ago and I'm looking to speed and clean it up. Each Sub performs > various actions based which can't be simplified or condensed more than > they have. > > I've created my DispatchHash for subs/patterns but I think I'm > confusing myself on actually doing the match and dispatch including > passing $Line to the sub. > > Any examples would be very welcome. > > Robert From robert.l.harris at gmail.com Wed Apr 20 07:58:38 2016 From: robert.l.harris at gmail.com (Robert L. Harris) Date: Wed, 20 Apr 2016 14:58:38 +0000 Subject: [Denver-pm] Dispatch Lists? In-Reply-To: <5716BC6D.5060505@thecommune.net> References: <5716BC6D.5060505@thecommune.net> Message-ID: With the for-each walking through the dispatch list, that seems to just be about the equivalent of the chain of if then statements. I started a simple tester and came up with this: Input Lines: This is Line1. This is Line3. This is Line2. And this script: #!/usr/bin/perl -w $| = 1; use strict; use diagnostics; my $User=$ENV{"LOGNAME"}; # GetOpt use vars qw( $opt_f ); use Getopt::Mixed; Getopt::Mixed::getOptions("f=s "); my $Line; my @Lines; my %DispatchHash = ( qr/Line1/ => \&Line1($Line), qr/Line2/ => \&Line2($Line), qr/Line3/ => \&Line3($Line), ); open(INPUT, "<$opt_f") || die "Can't open $opt_f $?\n"; while() { chomp; $Line=$_; print "\$Line :$Line:\n"; # print "\$_ :$_:\n"; # push(@Lines, $_); exit 0; } exit 0; # # Subs # sub Line1 { my $InputLine=$_[0] ||= "Undefined1"; print " Sub 1 :$InputLine:\n"; } sub Line2 { my $InputLine=$_[0] ||= "Undefined2"; print " Sub 2 :$InputLine:\n"; } sub Line3 { my $InputLine=$_[0] ||= "Undefined3"; print " Sub 3 :$InputLine:\n"; } Unfortunately, my output looks like this: Sub 1 :Undefined1: Sub 2 :Undefined1: Sub 3 :Undefined1: $Line :Line1: Where it should be: This is Line1. Sub 1 :This is Line1: This is Line3. Sub 3 :This is Line3: This is Line2. Sub 2 :This is Line2: Robert On Tue, Apr 19, 2016 at 5:25 PM Stuart A Johnston wrote: > Here's a simple example. I've just used $ARGV[0] as the input but you > could add another loop for your multi-line input. > > #!/usr/bin/perl > > use strict; > use v5.10; > > sub sub_foo { > say "foo: $_[0]"; > } > > sub sub_bar { > say "bar: $_[0]"; > } > > my @dispatch = ( > [ qr/foo/, \&sub_foo ], > [ qr/bar/, \&sub_bar ], > ); > > foreach my $d (@dispatch) { > my ($r, $sub) = @$d; > > if ($ARGV[0] =~ $r) { > $sub->($ARGV[0]); > next; > } > } > > > > On 04/19/2016 02:28 PM, Robert L. Harris wrote: > > > > Anyone have a straight forward script using dispatch lists? I have one > > ( 4500 lines by now ) which effectively does this: > > > > 1. Open input file > > 2. while { > > 3. $Line= > > 4. &Sub1("Line") if ( $Line =~ // ); > > 5. &Sub2("Line") if ( $Line =~ // ); > > 6. &Sub3("Line") if ( $Line =~ // ); > > 7. ... about 25 patterns now ... > > 8. } > > > > Yeah, it's ugly, it started out as a 30 line data munger about 2.5 years > > ago and I'm looking to speed and clean it up. Each Sub performs > > various actions based which can't be simplified or condensed more than > > they have. > > > > I've created my DispatchHash for subs/patterns but I think I'm > > confusing myself on actually doing the match and dispatch including > > passing $Line to the sub. > > > > Any examples would be very welcome. > > > > Robert > > _______________________________________________ > Denver-pm mailing list > Denver-pm at pm.org > http://mail.pm.org/mailman/listinfo/denver-pm > -------------- next part -------------- An HTML attachment was scrubbed... URL: From saj at thecommune.net Wed Apr 20 08:41:45 2016 From: saj at thecommune.net (Stuart Johnston) Date: Wed, 20 Apr 2016 10:41:45 -0500 Subject: [Denver-pm] Dispatch Lists? In-Reply-To: References: <5716BC6D.5060505@thecommune.net> Message-ID: <20160420104145.172923uz7ev6lfes@webmail.tuffmail.net> You are right that it is not an improvement performance-wise. I'd say it is easier to read and maintain but I suppose that is subjective. The problem is that you can't use a regex as hash key so you can't use a traditional dispatch table lookup. Also, you have to call the sub with the $Line param inside the loop, not in the hash. Quoting "Robert L. Harris" : > With the for-each walking through the dispatch list, that seems to just > be about the equivalent of the chain of if then statements. I started a > simple tester and came up with this: > > Input Lines: > This is Line1. > This is Line3. > This is Line2. > > And this script: > > #!/usr/bin/perl -w > $| = 1; > > use strict; > use diagnostics; > > my $User=$ENV{"LOGNAME"}; > > # GetOpt > use vars qw( $opt_f ); > use Getopt::Mixed; > Getopt::Mixed::getOptions("f=s "); > > > my $Line; > my @Lines; > my %DispatchHash = ( > qr/Line1/ => \&Line1($Line), > qr/Line2/ => \&Line2($Line), > qr/Line3/ => \&Line3($Line), > ); > > > open(INPUT, "<$opt_f") || die "Can't open $opt_f $?\n"; > while() { > chomp; > $Line=$_; > print "\$Line :$Line:\n"; > # print "\$_ :$_:\n"; > > # push(@Lines, $_); > > exit 0; > } > > exit 0; > > # > # Subs > # > sub Line1 { > my $InputLine=$_[0] ||= "Undefined1"; > print " Sub 1 :$InputLine:\n"; > } > > sub Line2 { > my $InputLine=$_[0] ||= "Undefined2"; > print " Sub 2 :$InputLine:\n"; > } > sub Line3 { > my $InputLine=$_[0] ||= "Undefined3"; > print " Sub 3 :$InputLine:\n"; > } > > > Unfortunately, my output looks like this: > Sub 1 :Undefined1: > Sub 2 :Undefined1: > Sub 3 :Undefined1: > $Line :Line1: > > Where it should be: > > This is Line1. > Sub 1 :This is Line1: > This is Line3. > Sub 3 :This is Line3: > This is Line2. > Sub 2 :This is Line2: > > Robert > > On Tue, Apr 19, 2016 at 5:25 PM Stuart A Johnston > wrote: > >> Here's a simple example. I've just used $ARGV[0] as the input but you >> could add another loop for your multi-line input. >> >> #!/usr/bin/perl >> >> use strict; >> use v5.10; >> >> sub sub_foo { >> say "foo: $_[0]"; >> } >> >> sub sub_bar { >> say "bar: $_[0]"; >> } >> >> my @dispatch = ( >> [ qr/foo/, \&sub_foo ], >> [ qr/bar/, \&sub_bar ], >> ); >> >> foreach my $d (@dispatch) { >> my ($r, $sub) = @$d; >> >> if ($ARGV[0] =~ $r) { >> $sub->($ARGV[0]); >> next; >> } >> } >> >> >> >> On 04/19/2016 02:28 PM, Robert L. Harris wrote: >> > >> > Anyone have a straight forward script using dispatch lists? I have one >> > ( 4500 lines by now ) which effectively does this: >> > >> > 1. Open input file >> > 2. while { >> > 3. $Line= >> > 4. &Sub1("Line") if ( $Line =~ // ); >> > 5. &Sub2("Line") if ( $Line =~ // ); >> > 6. &Sub3("Line") if ( $Line =~ // ); >> > 7. ... about 25 patterns now ... >> > 8. } >> > >> > Yeah, it's ugly, it started out as a 30 line data munger about 2.5 years >> > ago and I'm looking to speed and clean it up. Each Sub performs >> > various actions based which can't be simplified or condensed more than >> > they have. >> > >> > I've created my DispatchHash for subs/patterns but I think I'm >> > confusing myself on actually doing the match and dispatch including >> > passing $Line to the sub. >> > >> > Any examples would be very welcome. >> > >> > Robert >> >> _______________________________________________ >> Denver-pm mailing list >> Denver-pm at pm.org >> http://mail.pm.org/mailman/listinfo/denver-pm >> > From saj at thecommune.net Wed Apr 20 09:15:57 2016 From: saj at thecommune.net (Stuart Johnston) Date: Wed, 20 Apr 2016 11:15:57 -0500 Subject: [Denver-pm] Dispatch Lists? In-Reply-To: <20160420104145.172923uz7ev6lfes@webmail.tuffmail.net> References: <5716BC6D.5060505@thecommune.net> <20160420104145.172923uz7ev6lfes@webmail.tuffmail.net> Message-ID: <20160420111557.14663ualgie1hnqc@webmail.tuffmail.net> I should clarify that you *can* use a regex as a hash key but you can't do a direct hash lookup based on the regex match so you'd still have to loop on the keys. I also found an interesting solution in Perl Hacks, #98, if you happen to have a copy of that book. It uses Regexp::Assemble to combine pattern strings into a single regex. There is an example under "TRACKING REGULAR EXPRESSION MATCHES" in http://cpansearch.perl.org/src/RSAVAGE/Regexp-Assemble-0.37/README I don't think it is really worth the trouble though. Even with 25 patterns, you are not likely to see a significant difference in performance. Quoting Stuart Johnston : > You are right that it is not an improvement performance-wise. I'd > say it is easier to read and maintain but I suppose that is > subjective. The problem is that you can't use a regex as hash key so > you can't use a traditional dispatch table lookup. > > Also, you have to call the sub with the $Line param inside the loop, > not in the hash. > > > Quoting "Robert L. Harris" : > >> With the for-each walking through the dispatch list, that seems to just >> be about the equivalent of the chain of if then statements. I started a >> simple tester and came up with this: >> >> Input Lines: >> This is Line1. >> This is Line3. >> This is Line2. >> >> And this script: >> >> #!/usr/bin/perl -w >> $| = 1; >> >> use strict; >> use diagnostics; >> >> my $User=$ENV{"LOGNAME"}; >> >> # GetOpt >> use vars qw( $opt_f ); >> use Getopt::Mixed; >> Getopt::Mixed::getOptions("f=s "); >> >> >> my $Line; >> my @Lines; >> my %DispatchHash = ( >> qr/Line1/ => \&Line1($Line), >> qr/Line2/ => \&Line2($Line), >> qr/Line3/ => \&Line3($Line), >> ); >> >> >> open(INPUT, "<$opt_f") || die "Can't open $opt_f $?\n"; >> while() { >> chomp; >> $Line=$_; >> print "\$Line :$Line:\n"; >> # print "\$_ :$_:\n"; >> >> # push(@Lines, $_); >> >> exit 0; >> } >> >> exit 0; >> >> # >> # Subs >> # >> sub Line1 { >> my $InputLine=$_[0] ||= "Undefined1"; >> print " Sub 1 :$InputLine:\n"; >> } >> >> sub Line2 { >> my $InputLine=$_[0] ||= "Undefined2"; >> print " Sub 2 :$InputLine:\n"; >> } >> sub Line3 { >> my $InputLine=$_[0] ||= "Undefined3"; >> print " Sub 3 :$InputLine:\n"; >> } >> >> >> Unfortunately, my output looks like this: >> Sub 1 :Undefined1: >> Sub 2 :Undefined1: >> Sub 3 :Undefined1: >> $Line :Line1: >> >> Where it should be: >> >> This is Line1. >> Sub 1 :This is Line1: >> This is Line3. >> Sub 3 :This is Line3: >> This is Line2. >> Sub 2 :This is Line2: >> >> Robert >> >> On Tue, Apr 19, 2016 at 5:25 PM Stuart A Johnston >> wrote: >> >>> Here's a simple example. I've just used $ARGV[0] as the input but you >>> could add another loop for your multi-line input. >>> >>> #!/usr/bin/perl >>> >>> use strict; >>> use v5.10; >>> >>> sub sub_foo { >>> say "foo: $_[0]"; >>> } >>> >>> sub sub_bar { >>> say "bar: $_[0]"; >>> } >>> >>> my @dispatch = ( >>> [ qr/foo/, \&sub_foo ], >>> [ qr/bar/, \&sub_bar ], >>> ); >>> >>> foreach my $d (@dispatch) { >>> my ($r, $sub) = @$d; >>> >>> if ($ARGV[0] =~ $r) { >>> $sub->($ARGV[0]); >>> next; >>> } >>> } >>> >>> >>> >>> On 04/19/2016 02:28 PM, Robert L. Harris wrote: >>>> >>>> Anyone have a straight forward script using dispatch lists? I have one >>>> ( 4500 lines by now ) which effectively does this: >>>> >>>> 1. Open input file >>>> 2. while { >>>> 3. $Line= >>>> 4. &Sub1("Line") if ( $Line =~ // ); >>>> 5. &Sub2("Line") if ( $Line =~ // ); >>>> 6. &Sub3("Line") if ( $Line =~ // ); >>>> 7. ... about 25 patterns now ... >>>> 8. } >>>> >>>> Yeah, it's ugly, it started out as a 30 line data munger about 2.5 years >>>> ago and I'm looking to speed and clean it up. Each Sub performs >>>> various actions based which can't be simplified or condensed more than >>>> they have. >>>> >>>> I've created my DispatchHash for subs/patterns but I think I'm >>>> confusing myself on actually doing the match and dispatch including >>>> passing $Line to the sub. >>>> >>>> Any examples would be very welcome. >>>> >>>> Robert >>> >>> _______________________________________________ >>> Denver-pm mailing list >>> Denver-pm at pm.org >>> http://mail.pm.org/mailman/listinfo/denver-pm >>> >> > > > _______________________________________________ > Denver-pm mailing list > Denver-pm at pm.org > http://mail.pm.org/mailman/listinfo/denver-pm > From chris at fedde.us Mon Apr 25 17:51:03 2016 From: chris at fedde.us (Chris Fedde) Date: Mon, 25 Apr 2016 18:51:03 -0600 Subject: [Denver-pm] Dispatch Lists? In-Reply-To: References: Message-ID: My preferred approach is to use a class: This untested example uses named captures which are a recent perl feature. the Regexp /extract (? .*+) from string/ is "meta syntax" for a regexp that finds a method name in the input string. package Switch; sub add {...} sub delete {...} sub frobnicate {...} sub AUTOLOAD { die "unimplemented method called" } package Main; while (my $line = <>) { $line =~ /extract (? .*+) from string/; my $method = $+{method} or next; $ ignore lines that have no method Switch->$method($line); } On Tue, Apr 19, 2016 at 2:28 PM, Robert L. Harris wrote: > > Anyone have a straight forward script using dispatch lists? I have one ( > 4500 lines by now ) which effectively does this: > > > 1. Open input file > 2. while { > 3. $Line= > 4. &Sub1("Line") if ( $Line =~ // ); > 5. &Sub2("Line") if ( $Line =~ // ); > 6. &Sub3("Line") if ( $Line =~ // ); > 7. ... about 25 patterns now ... > 8. } > > Yeah, it's ugly, it started out as a 30 line data munger about 2.5 years > ago and I'm looking to speed and clean it up. Each Sub performs various > actions based which can't be simplified or condensed more than they have. > > I've created my DispatchHash for subs/patterns but I think I'm > confusing myself on actually doing the match and dispatch including passing > $Line to the sub. > > Any examples would be very welcome. > > Robert > > _______________________________________________ > Denver-pm mailing list > Denver-pm at pm.org > http://mail.pm.org/mailman/listinfo/denver-pm > > -------------- next part -------------- An HTML attachment was scrubbed... URL: