|
|
|
|
|
|
| Author |
Message |
James *nix forums Guru
Joined: 09 Jun 2003
Posts: 306
|
Posted: Wed Jun 21, 2006 7:13 pm Post subject:
Re: How to select subroutine
|
|
|
On Wed, 21 Jun 2006 16:20:45 +0000, Glenn Jackman wrote:
| Quote: | At 2006-06-20 08:17PM, James <hoosier45678@hotmail.com> wrote:
my $output = handler{$function}->(@ARGUMENTS);
missing $ -----------^
|
Good eye. I didn't actually test it. |
|
| Back to top |
|
 |
Glenn Jackman *nix forums addict
Joined: 19 Apr 2005
Posts: 97
|
Posted: Wed Jun 21, 2006 4:20 pm Post subject:
Re: How to select subroutine
|
|
|
At 2006-06-20 08:17PM, James <hoosier45678@hotmail.com> wrote:
| Quote: | my $output = handler{$function}->(@ARGUMENTS);
missing $ -----------^ |
--
Glenn Jackman
Ulterior Designer |
|
| Back to top |
|
 |
Ben Morrow *nix forums Guru Wannabe
Joined: 24 Apr 2006
Posts: 193
|
Posted: Wed Jun 21, 2006 3:54 am Post subject:
Re: How to select subroutine
|
|
|
Quoth "Jan Fure" <janfure@gmail.com>:
| Quote: |
Ben Morrow wrote:
Yes, but it would be a bad idea. A better answer would be to use a
proper lookup table (in Perl, a hash).
I would do this like (untested):
my %dispatch = (
sr2 => sub { $_[1] ** 2 },
sr3 => sub { $_[1] ** 3 },
);
If I understand you right, you are proposing a hash, with keys from my
data, and anonymous subroutines linked to the keys.
|
Yes.
| Quote: | For my actual code, this would be quite ugly, as the subroutines are
20+ lines of code.
|
FWIW, I don't see how
sub foo {
# 20 lines
}
sub bar {
# 20 lines
}
is substantially less ugly than
my %dispatch = (
foo => sub {
# 20 lines
},
bar => sub {
# 20 lines
},
);
; especially as the subs are all then kept together in an indented
block. However, if you disagree, then you can use
sub foo { ... }
sub bar { ... }
my %dispatch = (
foo => \&foo,
bar => \&bar,
);
just as easily.
| Quote: | I also need the program to exit with appropriate error message, if
there is no match between existing subroutine and requested subroutine,
|
perldoc -f exists
| Quote: | Could you elaborate on why it is a bad idea to let the subroutine name
be contained in the data?
|
Think about what happens if you get a key in your data that is the name
of some other sub, not part of your dispatch table.
If your next thought is to create a special package to keep these subs
in, then consider that a package is just a magical hash, and when you
don't need the magic (like now) it's safer, cleaner and faster to just
use a regular hash.
Ben
--
All persons, living or dead, are entirely coincidental.
benmorrow@tiscali.co.uk Kurt Vonnegut |
|
| Back to top |
|
 |
Tad McClellan *nix forums Guru
Joined: 09 Mar 2005
Posts: 1647
|
Posted: Wed Jun 21, 2006 12:54 am Post subject:
Re: How to select subroutine
|
|
|
Jan Fure <janfure@gmail.com> wrote:
| Quote: | I also need the program to exit with appropriate error message, if
there is no match between existing subroutine and requested subroutine,
|
die "appropriate error message" unless exists $dispatch{$ARGUMENTS[0]};
--
Tad McClellan SGML consulting
tadmc@augustmail.com Perl programming
Fort Worth, Texas |
|
| Back to top |
|
 |
Tad McClellan *nix forums Guru
Joined: 09 Mar 2005
Posts: 1647
|
|
| Back to top |
|
 |
simon.chao@gmail.com *nix forums addict
Joined: 06 Oct 2005
Posts: 98
|
Posted: Wed Jun 21, 2006 12:36 am Post subject:
Re: How to select subroutine
|
|
|
Jan Fure wrote:
| Quote: | Ben Morrow wrote:
Yes, but it would be a bad idea. A better answer would be to use a
proper lookup table (in Perl, a hash).
I would do this like (untested):
my %dispatch = (
sr2 => sub { $_[1] ** 2 },
sr3 => sub { $_[1] ** 3 },
);
Ben
Thanks for replying!
If I understand you right, you are proposing a hash, with keys from my
data, and anonymous subroutines linked to the keys.
For my actual code, this would be quite ugly, as the subroutines are
20+ lines of code.
This was just the shortest code I could come up with, that illustrated
the constraints:
1. Sub routine aquired from data.
2. Ability to pass output to the original function/subroutne call.
I also need the program to exit with appropriate error message, if
there is no match between existing subroutine and requested subroutine,
but I omitted that from the example code to keep it from getting too
long.
|
this is called a dispatch table. |
|
| Back to top |
|
 |
Tad McClellan *nix forums Guru
Joined: 09 Mar 2005
Posts: 1647
|
Posted: Wed Jun 21, 2006 12:35 am Post subject:
Re: How to select subroutine
|
|
|
Jan Fure <janfure@gmail.com> wrote:
| Quote: | I need to be able to select which subroutine to process a string with
based on the contents of the string.
|
That is known in computer science as a "dispatch table".
| Quote: | I have written a code example of this, that uses a lookup table.
Is there a sensible way to do this without the lookup table,
|
No.
(but you can make a much nicer lookup table using a hash and coderefs.)
| Quote: | i.e., can
I let the parsed string value be the subroutine name?
|
Yes you can, but you don't want to.
That would be using Symbolic References, which should be avoided
when possible...
| Quote: | #!/usr/local/bin/perl -w
use strict;
|
.... and use strict disallows using symrefs anyway.
| Quote: | my @DATA = <DATA>;
foreach (@DATA) {
|
Why read all of the lines when you are only going to process one
line at a time anyway?
while ( <DATA> ) {
| Quote: | chomp;
my @ARGUMENTS = split / /;
my $output = subselect(@ARGUMENTS);
|
my %subs = ( sr2 => \&sr2, sr3 => \&sr3 ); # dispatch table
my $output = $subs{$ARGUMENTS[0]}->(@ARGUMENTS); # call the coderef
| Quote: | sub subselect {
if ($_[0] eq 'sr2') {
my $return_value = sr2(@_);
|
And here we have the rare case where using an ampersand on a function
call _is_ what you want:
my $return_value = &sr2;
(but passing @_ explicitly is "better" IMO.)
| Quote: | return $return_value;
}
if ($_[0] eq 'sr3') {
my $return_value = sr3(@_);
return $return_value;
}
}
|
--
Tad McClellan SGML consulting
tadmc@augustmail.com Perl programming
Fort Worth, Texas |
|
| Back to top |
|
 |
James *nix forums Guru
Joined: 09 Jun 2003
Posts: 306
|
Posted: Wed Jun 21, 2006 12:17 am Post subject:
Re: How to select subroutine
|
|
|
On Tue, 20 Jun 2006 17:03:32 -0700, Jan Fure wrote:
| Quote: | If I understand you right, you are proposing a hash, with keys from my
data, and anonymous subroutines linked to the keys.
For my actual code, this would be quite ugly, as the subroutines are
20+
lines of code.
|
they don't have to be anonymous, per se.
%handlers = (
sr2 => \&sr2,
sr3 => \&sr3,
);
while(<DATA>)
{
chomp;
my ($function, @ARGUMENTS) = split / /;
die "No handler for $function" unless defined $handler{$function};
my $output = handler{$function}->(@ARGUMENTS);
print "The chained output of 2 subroutines is $output\n";
}
sub sr2
{
$_[0] ** 2;
}
| Quote: | This was just the shortest code I could come up with, that illustrated
the constraints:
1. Sub routine aquired from data.
2. Ability to pass output to the original function/subroutne call. I
also need the program to exit with appropriate error message, if there
is no match between existing subroutine and requested subroutine, but I
omitted that from the example code to keep it from getting too long.
Could you elaborate on why it is a bad idea to let the subroutine name
be contained in the data?
|
depends on the source of the data, but perldoc -f eval |
|
| Back to top |
|
 |
Jan Fure *nix forums beginner
Joined: 20 Jun 2006
Posts: 2
|
Posted: Wed Jun 21, 2006 12:03 am Post subject:
Re: How to select subroutine
|
|
|
Ben Morrow wrote:
| Quote: | Yes, but it would be a bad idea. A better answer would be to use a
proper lookup table (in Perl, a hash).
I would do this like (untested):
my %dispatch = (
sr2 => sub { $_[1] ** 2 },
sr3 => sub { $_[1] ** 3 },
);
Ben
Thanks for replying! |
If I understand you right, you are proposing a hash, with keys from my
data, and anonymous subroutines linked to the keys.
For my actual code, this would be quite ugly, as the subroutines are
20+ lines of code.
This was just the shortest code I could come up with, that illustrated
the constraints:
1. Sub routine aquired from data.
2. Ability to pass output to the original function/subroutne call.
I also need the program to exit with appropriate error message, if
there is no match between existing subroutine and requested subroutine,
but I omitted that from the example code to keep it from getting too
long.
Could you elaborate on why it is a bad idea to let the subroutine name
be contained in the data?
Is there a way to improve the structure of the code I wrote, while
keeping the subroutines around? In my production code, I expect there
might be 15+ different sub routines.
Jan |
|
| Back to top |
|
 |
Ben Morrow *nix forums Guru Wannabe
Joined: 24 Apr 2006
Posts: 193
|
Posted: Tue Jun 20, 2006 11:22 pm Post subject:
Re: How to select subroutine
|
|
|
Quoth "Jan Fure" <janfure@gmail.com>:
| Quote: |
I need to be able to select which subroutine to process a string with
based on the contents of the string.
I have written a code example of this, that uses a lookup table.
Is there a sensible way to do this without the lookup table, i.e., can
I let the parsed string value be the subroutine name?
|
Yes, but it would be a bad idea. A better answer would be to use a
proper lookup table (in Perl, a hash).
| Quote: |
#!/usr/local/bin/perl -w
|
use warnings;
is the modern version on -w.
| Quote: | use strict;
my @DATA = <DATA>;
foreach (@DATA) {
|
If you want the data line-by-line, then read it line-by line.
| Quote: | chomp;
my @ARGUMENTS = split / /;
my $output = subselect(@ARGUMENTS);
print "The chained output of 2 subroutines is $output\n";
}
sub subselect {
if ($_[0] eq 'sr2') {
my $return_value = sr2(@_);
return $return_value;
}
if ($_[0] eq 'sr3') {
my $return_value = sr3(@_);
return $return_value;
}
}
sub sr2 {
my $x2 = $_[1] ** 2;
return $x2;
}
sub sr3 {
my $x3 = $_[1] ** 3;
return $x3;
}
__DATA__
sr2 3.456
sr3 2
sr2 45
|
I would do this like (untested):
my %dispatch = (
sr2 => sub { $_[1] ** 2 },
sr3 => sub { $_[1] ** 3 },
);
local $\ = "\n"; # saves printing them all the time
while (<DATA>) {
my @args = split; # this doesn't quite do what you did before,
# but it's likely more flexible and more use.
# And you don't need the chomp.
my $output = $dispatch{$args[0]}->(@args);
print "the output of a sub in a dispatch table is $output";
}
__DATA__
sr2 3.456
sr3 2
sr2 45
I presume 'sr2' and 'sr3' are just examples? If not, I'd extract the '2'
and use it as a parameter rather than writing two separate subs.
Ben
--
The Earth is degenerating these days. Bribery and corruption abound.
Children no longer mind their parents, every man wants to write a book,
and it is evident that the end of the world is fast approaching.
Assyrian stone tablet, c.2800 BC benmorrow@tiscali.co.uk |
|
| Back to top |
|
 |
Jan Fure *nix forums beginner
Joined: 20 Jun 2006
Posts: 2
|
Posted: Tue Jun 20, 2006 10:32 pm Post subject:
How to select subroutine
|
|
|
Hi;
I need to be able to select which subroutine to process a string with
based on the contents of the string.
I have written a code example of this, that uses a lookup table.
Is there a sensible way to do this without the lookup table, i.e., can
I let the parsed string value be the subroutine name?
Jan
#!/usr/local/bin/perl -w
use strict;
my @DATA = <DATA>;
foreach (@DATA) {
chomp;
my @ARGUMENTS = split / /;
my $output = subselect(@ARGUMENTS);
print "The chained output of 2 subroutines is $output\n";
}
sub subselect {
if ($_[0] eq 'sr2') {
my $return_value = sr2(@_);
return $return_value;
}
if ($_[0] eq 'sr3') {
my $return_value = sr3(@_);
return $return_value;
}
}
sub sr2 {
my $x2 = $_[1] ** 2;
return $x2;
}
sub sr3 {
my $x3 = $_[1] ** 3;
return $x3;
}
__DATA__
sr2 3.456
sr3 2
sr2 45 |
|
| Back to top |
|
 |
Google
|
|
| Back to top |
|
 |
|
|
The time now is Fri Nov 21, 2008 6:28 am | All times are GMT
|
|
Xbox Mod Chip | Loans | Free Online RPG | Mortgage Calculator | Books
|
|
Copyright © 2004-2005 DeniX Solutions SRL
|
|
|
|
Other DeniX Solutions sites:
Unix/Linux blog |
electronics forum |
medicine forum |
science forum |
|
|
Privacy Policy
|
Powered by phpBB © 2001, 2005 phpBB Group
|
|