Using a variable to call a sub-routine...

B

Big Jay

Hi all,

I'm trying to call a sub-routine based on the value of a variable.

More specifically, I'm developing a menu system, where each level of the
menu has it's own sub-routine, but for a generalized "back" function, I'm
trying to call the last menu based on a variable, something like:

$lastMenu = apiMenu;

&$lastMenu; #I want this to be the same as calling &apiMenu

Does this make any sense?

Any help is greatly appreciated!
 
A

A. Sinan Unur

I'm trying to call a sub-routine based on the value of a variable.

More specifically, I'm developing a menu system, where each level of
the menu has it's own sub-routine, but for a generalized "back"
function, I'm trying to call the last menu based on a variable,
something like:

$lastMenu = apiMenu;

&$lastMenu; #I want this to be the same as calling &apiMenu

Use a hash table to map menu names to menu handlers.

Sinan
 
B

Big Jay

I think I'll try making a default menu functions sub-routine and pass it
arguments for things like last menu... That should do the trick.
 
M

Matt Garrish

Big Jay said:
Hi all,

I'm trying to call a sub-routine based on the value of a variable.

More specifically, I'm developing a menu system, where each level of the
menu has it's own sub-routine, but for a generalized "back" function, I'm
trying to call the last menu based on a variable, something like:

$lastMenu = apiMenu;

&$lastMenu; #I want this to be the same as calling &apiMenu

Does this make any sense?

They're called symrefs, and they're to be avoided. It's always better to use
a hash:

my %subs = ( apiMenu => \&apiMenu );
my $lastMenu = 'apiMenu';
$subs{$lastMenu}();

Matt
 
T

Tad McClellan

I'm trying to call a sub-routine based on the value of a variable.


That is what is known as a "dispatch table".

You'll need to learn a bit about references to implement
a dispatch table in Perl.

(the word "subroutine" is not hyphenated.)

More specifically, I'm developing a menu system, where each level of the
menu has it's own sub-routine, but for a generalized "back" function, I'm
trying to call the last menu based on a variable, something like:

$lastMenu = apiMenu;

&$lastMenu; #I want this to be the same as calling &apiMenu


-------------------
#!/usr/bin/perl
use warnings;
use strict;

my %menu_funcs = ( # a dispatch table
Open => \&open_file,
Edit => \&edit_file,
Close => \&close_file,
);

foreach my $menu_choice ( 'Open', 'Edit', 'Close' ) {
$menu_funcs{ $menu_choice }->(); # or: &{ $menu_funcs{ $menu_choice } }
}

sub open_file { warn "open_file() got called\n" }
sub edit_file { warn "edit_file() got called\n" }
sub close_file { warn "close_file() got called\n" }
 
R

robic0

That is what is known as a "dispatch table".
Maybe Tad, you can explain "dispatch table" a phrase used
exclusively for NT drivers...
Expanding out of Perl Tad?
You'll need to learn a bit about references to implement
a dispatch table in Perl.
You might even have to learn NT driver developer package...
(the word "subroutine" is not hyphenated.)
Your developing a "menu system" in Perl? Hey Perl is *not* Windows!!!!!!!!!!!!!
Take a Windows developer class from me. Do you know at least C ?
-------------------
#!/usr/bin/perl
use warnings;
use strict;

my %menu_funcs = ( # a dispatch table
Open => \&open_file,
Edit => \&edit_file,
Close => \&close_file,
);

foreach my $menu_choice ( 'Open', 'Edit', 'Close' ) {
$menu_funcs{ $menu_choice }->(); # or: &{ $menu_funcs{ $menu_choice } }
}

sub open_file { warn "open_file() got called\n" }
sub edit_file { warn "edit_file() got called\n" }
sub close_file { warn "close_file() got called\n" }
-------------------

Sorry man, its all bullshit.
 
R

robic0

They're called symrefs, and they're to be avoided. It's always better to use
a hash:
Symrefs? Stand for Symbolic References?

Can you please explain, for the beginners, when you use such wild assed terms..
The FLAWWED_FAQ tries I know rescue beginners when it sees such phrases
(that seem to make sence).

However, gone are the days of intellecutal arragoance! If you think your
audience doesen't understand your logic or analogy, its up to *YOU* to
provide the full documentation in your words.

Buddy, who the **** knows what your talking about? Don't invoke
Einstein's theory of realtivity with out explaining yourself!!

I'm gonna hold everyone to this, period !!

-<snip>-
 
U

Uri Guttman

"r" == robic0 <robic0> writes:

r> Maybe Tad, you can explain "dispatch table" a phrase used
r> exclusively for NT drivers...
r> Expanding out of Perl Tad?

hmm, did your addlepated brain ever allow the possibility that the term
dispatch table is slightly older than nt? and the concept is even older
than that? you really think that redmond both invented the concept and
the term? i was coding dispatch tables way before uncle bill robbed his
first billion. but you won't understand this anymore than you know why
the sky is blue.

how do you function in the real world with such delusions and
miscomprehensions? but your alter ego rm will soon pop in. ever notice
how the two of you are never seen at the same time?

uri
 
U

/usr/ceo

robic0 said:
Maybe Tad, you can explain "dispatch table" a phrase used
exclusively for NT drivers...
Expanding out of Perl Tad?

Uh, robic0...?? Don't make one of us have to track you down by IP,
come to your cubical at the library, and pull out all your octets one
by one with needle-nosed pliers, ok? Your trolling isn't welcome here.
Maybe try one of the alt groups or something, hmmmm???

/usr/ceo
 
D

David K. Wall

Tad McClellan said:
That is what is known as a "dispatch table".

You'll need to learn a bit about references to implement
a dispatch table in Perl.

(the word "subroutine" is not hyphenated.)

I wrote a tentative entry for the FAQ about this a year or two ago,
but never quite got around to submitting it, mainly because I
thought it should be vetted by some with more knowledge and
experience than myself.

Anyway, here it is:



How do I call a subroutine when I have the name of the subroutine?
How do I use a dispatch table?

A dispatch table is just a special name for a hash with code
references. (see L<perlref>) The code references can be from any
source, for example, references to named subroutines in or imported
into a module, references to fully qualified subroutine names, or
anonymous code references.

Here is an example of a dispatch table:

my %dispatch = (
update => \&update,
add => \&add,
other => \&Foo::bar,
error => sub { die "Error: @_" }
default => \&do_something,
);

Put the creation of the dispatch table outside of any subroutine
that uses it so it (the dispatch table) is created at compile time
and not recreated in each call to the subroutine that does the
dispatching.

If we have a desired name in the scalar $input, the associated
subroutine can be called using $dispatch{$input}->().

The code should always handle the case where the input value is not
a key of %dispatch, so we might implement the call like this:

($dispatch{$input} || $dispatch{'default'})->(@arguments);
 
U

Uri Guttman

DKW> How do I call a subroutine when I have the name of the subroutine?
DKW> How do I use a dispatch table?

DKW> A dispatch table is just a special name for a hash with code
DKW> references. (see L<perlref>) The code references can be from any
DKW> source, for example, references to named subroutines in or imported
DKW> into a module, references to fully qualified subroutine names, or
DKW> anonymous code references.

A dispatch table is just a special name for a hash which holds pairs of
name/code references for its keys/values. The code references can refer
to named subs, anonymous subs, package local subs or fully qualified
subs.


DKW> Here is an example of a dispatch table:

DKW> my %dispatch = (
DKW> update => \&update,
DKW> add => \&add,
DKW> other => \&Foo::bar,
DKW> error => sub { die "Error: @_" }
DKW> default => \&do_something,
DKW> );

DKW> Put the creation of the dispatch table outside of any subroutine
DKW> that uses it so it (the dispatch table) is created at compile time
DKW> and not recreated in each call to the subroutine that does the
DKW> dispatching.

and make sure it is initialized before it gets used. a classic and
subtle bug is declaring the table near the sub that does the
dispatching. if this sub gets called before the table assignment is
done, it will dispatch on an empty table. if this code is in a module,
it will probably not fail that way since the base code of the module
will be executed including the table assignment. but if this is all in
the main script, the call could be made at the top whereas the
assignment is lower down. then you should wrap the assignment AND its
dispatching sub into a single BEGIN block:

BEGIN {

my %dispatch = ( blah ...
) ;

sub handle_dispatch {

blah
}
}

DKW> If we have a desired name in the scalar $input, the associated
DKW> subroutine can be called using $dispatch{$input}->().

DKW> The code should always handle the case where the input value is not
DKW> a key of %dispatch, so we might implement the call like this:

DKW> ($dispatch{$input} || $dispatch{'default'})->(@arguments);

the default shouldn't be an entry in the dispatch table unless it is
allowed to be called by that name.

another point is that you can have multiple names calling the same
code. this effectively allows aliases for the code. one variation is
that the name is also passed as an argument to the code to handle
similar cases in one sub. also in some designs you don't allow a default
and if the name is not valid you issue some error.

dispatch tables are a great tool but you need to make sure this FAQ
covers enough points to make it useful. and when you finish this, just
send it into the FAQ autopost thing and the cabal will take a look at
it. i would support adding it to the FAQ.

uri
 
B

Brian McCauley

/usr/ceo said:
Your trolling isn't welcome here.

Do you really imagine that is is probable that the troll doesn't know
this?

You are feeding the troll.

Please consider applying the following guidelines:

* Never directly follow-up a troll's posts.

* Never directly address any statement to a troll.

* As much as possible avoid mentioning a troll by name.
 
R

robic0

Hi all,

I'm trying to call a sub-routine based on the value of a variable.

More specifically, I'm developing a menu system, where each level of the
menu has it's own sub-routine, but for a generalized "back" function, I'm
trying to call the last menu based on a variable, something like:

$lastMenu = apiMenu;

&$lastMenu; #I want this to be the same as calling &apiMenu

Does this make any sense?

Any help is greatly appreciated!

I guess I'll try to appretiate your post one more time, being in a
diffrent frame of mind.

Like I said, don't really know *what* type of menu system your talking about,
the availability of options on each level, saved frames, and so forth..

It does not appear you want anything other than a level scalar array of hashes
that contain sub references to handlers that know and where it is and can react,
based on some interpreted *key* selected via keyboard (?) input.

The sub's probably have identical parameters, or passed a constant structure
from which more sub/level, individual data can be processed. This is not easy.

Also, you may want to save state of the data previously entered if its revisited.
Likewise, you may want to carry around a master data structure that has been sucessfully
populated from previous visits as you progress down the menu tree towards the
final *SUBMIT/SAVE* conclusion. Again not easy. But entirely possible.

Consider that its a windows menu tree, where you are calling successive dialog's,
populating a master data structure along the way. A cancel out of a single dialog
invalidates *only* a portion of the master that you are populating. Consecutive
<backspace> could load previously entered data (incase the user just wanted to
change one item), but would probably invalidate the forward data if a backward
change deems it so.

.............

One way is:

# in key form, @menutext_hasharrays contains "Text" to display and
# corresponding index to the selected @m(x) that is current.

@menutext_hasharrays = (
# main
{'N' => [1, "'N'ext"], 'Q' => [3, "'Q'uit"],
'A' => [4, "'A'item"], 'B' => [5, "'B'item"], 'C' => [6, "'C'item"] },
# level 1
{'N' => [1, "'N'ext"], 'B' => [2, "'B'ack"], 'Q' => [3, "'Q'uit"],
'A' => [4, "'A'item"], 'B' => [5, "'B'item"], 'C' => [6, "'C'item"] },
# level 2
{'N' => [1, "'N'ext"], 'B' => [2, "'B'ack"], 'Q' => [3, "'Q'uit"],
'A' => [4, "'A'item"], 'B' => [5, "'B'item"] },
# level 3
{'N' => [1, "'N'ext"], 'B' => [2, "'B'ack"], 'Q' => [3, "'Q'uit"],
'A' => [4, "'A'item"], 'B' => [5, "'B'item"], 'C' => [6, "'C'item"] },
);

# @m(x) handler array's:
# index 0 always equals index to @menutext_hasharrays (for menu display options and
# holds indexes to handlers at the current level, this so a particular item need not
# be in order when displaying the option),
# index 1 always equals ref to "next" @m(x) array
# index 2 always equals ref to "last" @m(x) array (if back)
# index 3 always equals ref to "quit", can be custom specific to a menu ..
# index 4 - ... are the specific handlers for this menu level
# indexes > 2 are handlers

@mm = (0, \@m1, undef, \&quit);
@m1 = (1, \@m2, \@mm, \$quit, \&h11, \&h12, \&h13);
@m2 = (2, \@m3, \@m1, \$quit, \&h21, \&h22);
@m3 = (3, undef, \@m2, \$quit, \&h31, \&h32, \&h33);

..........

The rest is left as an exercise.

You have to read between the lines. All values in the anom array's in
@menutext_hasharrays are arbitrary except for the indexes into the @m(x) handler array's
The concept is driven from the knowledge of initially starting with a known @m(x) array
by default.

This is one of several ways to implement this in Perl, depending on your perspective.
There is always a *static* degree to this process. It *always* has some degree of
indirection, ie: building tables of references to others.

This is for character driven menu's. There's another way which is a derritive of this
that involves further indirection might drive you insane to even think about it.
Or that I don't care to explain...

The graphic method and the issues discussed above all can work depending on what wants
to be accomplished.

Hey, I'm not getting paid for this shit....

robic0
 
R

robic0

Do you really imagine that is is probable that the troll doesn't know
this?

You are feeding the troll.

Please consider applying the following guidelines:

* Never directly follow-up a troll's posts.

* Never directly address any statement to a troll.

* As much as possible avoid mentioning a troll by name.

K, Brian McCauley is the troll..... sorry I could not resist!
 
R

robic0

Uh, robic0...?? Don't make one of us have to track you down by IP,
come to your cubical at the library, and pull out all your octets one
by one with needle-nosed pliers, ok? Your trolling isn't welcome here.
Maybe try one of the alt groups or something, hmmmm???

/usr/ceo

This coming from a user who decides to take a directory name.
God help all the knowledge to date *NOT* reset on this faggat ...
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,756
Messages
2,569,535
Members
45,008
Latest member
obedient dusk

Latest Threads

Top