import-bot (20211) [Avatar] Offline
#1
[Originally posted by lsanger]

Andrew,

I typed in your dispatch table from pp. 152-3 and it worked just fine. As a
self-drill I decided to convert a subroutine in a program I wrote so that it
used a dispatch table.

The original code, which works (don't ask what the program does--it's totally
useless, but was educational to write):
sub direct {
my $command = $_[0];
edit($command) if $command =~ m/^d+$/ ;
up_or_down($command) if $command eq 'u' || $command eq 'd';
&rewrap if $command eq 'w';
&goto if $command eq 'g';
save(@allines) if $command eq 's';
&open_file if $command eq 'o';
if ( $command !~ m/^d+$/ && $command ne 'u' && $command ne 'd' &&
$command ne 'w' && $command ne 'g' && $command ne 's' &&
$command ne 'o') {
$error_msg = "Not a recognized command.";
}
}

The new code, including the dispatch table, is this:
sub direct {
my $command = $_[0];
print "my command is $command, master
"; # for debugging
my %dispatch_table = ( u => up_or_down($command),
d => up_or_down($command),
w => &rewrap,
s => &save(@allines),
o => &open_file,
);
print "$command = $command right now
"; # for debugging
if ( $dispatch_table{$command} ) {
$dispatch_table{$command}->();
} elsif ( $command =~ m/^d+$/ ) {
edit($command);
} else {
$error_msg = "Not a recognized command.";
}
}

When I run the exact same program with the latter code instead of the former,
the program doesn't work. If I input anything at all (input is passed to this
sub from a different sub), the program appears to execute the &save
subroutine. Before the script gets to the dispatch table, the line "my
command is XYZ" is printed out as expected, but the line "$command = XYZ right
now," which immediately follows the dispatch table, isn't printed out. The
&save subroutine works more or less correctly, unless I use the cancel option,
which then puts me back in the &direct subroutine, where I get this error:
"Not a CODE reference at lute2 line 75, <STDIN> chunk 3." Lines 75-6 are:

if ( $dispatch_table{$command} ) {
$dispatch_table{$command}->();

I don't get it...

I imagine this the problem here is idiotically simple, but I can't figure it
out.

Larry Sanger
import-bot (20211) [Avatar] Offline
#2
Re: Dispatch table not working
[Originally posted by lsanger]

Sorry, there should have been backslashes in front of the following subroutine
calls (there are in my script, but apparently they need to be escaped when
copied to this forum):

> my %dispatch_table = ( u => up_or_down($command),
> d => up_or_down($command),
> w => &rewrap,
> s => &save(@allines),
> o => &open_file,
> );

Larry Sanger
import-bot (20211) [Avatar] Offline
#3
Re: Dispatch table not working
[Originally posted by jandrew]

> I imagine this the problem here is idiotically simple, but I can't
> figure it out.

Well, it is simple, but I wouldn't call it idiotically simple smilie

To create a reference to an existing named subroutine you must use
the ampersand and you can't pass arguments when creating the
reference. Without the ampersand, and/or if you pass arguments (even
an empty arg list), you do not get a reference to a function but a
reference to the return value of the subroutine.


$cref = &some_func; # OK ref to some_func

$cref = some_func; # not OK (no ampersand)
$cref = &some_func(); # not OK (argument list)
$cref = &some_func(args); # not OK (argument list)


If you want to pass arguments determined at runtime that vary per
dispatched command, wrap ordinary subroutine calls in an anonymous
subroutine:


my %dispatch = (
u => sub{ up_or_down($command) },
d => sub{ up_or_down($command) },
w => &wrap,
s => sub{ save(@allines) },
o => &open_file,
);

You might want to wrap them all in anoymous subroutines in this
case just for consistency.

Hope it helps.

regards,
andrew
import-bot (20211) [Avatar] Offline
#4
Re: Dispatch table not working
[Originally posted by lsanger]

Thanks a lot, Andrew--that did it. Always helps to know the rules...

--Larry