The Author Online Book Forums are Moving

The Author Online Book Forums will soon redirect to Manning's liveBook and liveVideo. All book forum content will migrate to liveBook's discussion forum and all video forum content will migrate to liveVideo. Log in to liveBook or liveVideo with your Manning credentials to join the discussion!

Thank you for your engagement in the AoF over the years! We look forward to offering you a more enhanced forum experience.

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