in reply to Subroutine references inside of a hash with arguments.

First some points that will help you forever:
#!/usr/bin/perl use warnings; # can be simplified to just #!/usr/bin/perl -w # this will work even on Windows!! Windows Perl doesn't look # at the path, but it does look at the -w trailing thing. You will see this often at the start of a Perl program: #!/usr/bin/perl -w use strict;
Warnings has a runtime impact, but normally I would "use warnings" except in the case of very well debugged, high performance code and even then I would think twice about leaving warnings out!

I would add "use strict;". Strict is a compile time thing and has no impact upon code execution time. It enforces scoping rules as one of the main things. Your code doesn't compile under "strict".

The syntax: &sub_name is deprecated. You can just say "sub_name;" or "sub_name();, or sub_name($parm1, $parm2)".

sub menu_system($bs_index){....} is wrong in Perl.
Perl does have a prototype mechanism but is not strongly typed (to say the least!). In any event the Perl prototype mechanism could say something like: I require at least 3 and possibly 4 scalar values. Calling the sub with 2 or 5 values would be rejected during compile. Most Perl programs don't even worry about this and for your first code, I would wouldn't either and I'm not even going to demonstrate this syntax because I don't think you need it.

A Perl sub gets a "stack" of stuff. The Perl subroutine does what it wants with this "stack of stuff".

Update: I forgot to add this sub param stuff:

sub A { my $parm1 = shift; #effect: literally shift off the stack passed } sub B { my ($p1,$p2,$p3) = @_; #effect: make copy from stack passed }
I am a bit confused with your code, but I will present the Perl way of a standard command loop that uses text as a command:
while ( (print "Enter Command: "), (my $line = <STDIN>) !~ /^\s*q(uit)?\s*$/i ) { next if $line =~ /^\s*$/; #skip new lines next if $line =~/^\s*skip/i; #skip is a no op command insert if $line =~/^\s*insert/i; #do insert command delete if $line =~/^\s*delete/i; #do delete command #...etc.. } sub insert() {...} sub delete() {...}
There are of course many variations on the above. But it is short and to the point.

I recommend not trying to be overly complex. I have written fancy hash driven dispatch tables, but I don't think that is what you need.

Replies are listed 'Best First'.
Re^2: Subroutine references inside of a hash with arguments.
by chromatic (Archbishop) on Jul 25, 2009 at 07:27 UTC
    use warnings; can be simplified to just #!/usr/bin/perl -w

    That's not true; the warnings pragma has lexical effects. The -w flag does not.

    Strict is a compile time thing and has no impact upon code execution time.

    Strict reference checking occurs at runtime.

    It enforces scoping rules as one of the main things.

    strict has nothing to do with scoping rules. You can use fully qualified package globals everywhere and strict will not complain.

    The syntax: &sub_name is deprecated.

    Discouraged, perhaps (except for tail calls) but not deprecated.

    You can just say "sub_name;"

    Not always -- if you have strict enabled.

    #effect: literally shift off the stack passed

    This is misleading. (How do you pass a stack?)

    #effect: make copy from stack passed

    This is doubly misleading.

      I would be curious to learn what lexical effects the "use warnings" pragma has that the -w flag doesn't? I don't think that there are any at all. There are some differences that I seem to remember...maybe you can turn warnings off, if the -w flag is used but not if "use warnings" is in the source code, for example, maybe?

      Strict is a compile time thing - not run time. Scoping like "my vars" is a big part of what "use strict" enforces - use of a fully qualified name in another module is completely within the "rules of strict".

      I would highly recommend Randal Schwartz'es book, "Effective Perl Programming", see item 36. For example to learn more about -w, see page 143.

      I don't think we need to get into a big brouhaha about legalistic sounding terminology about "discouraged" vs "deprecated". Suffice it to say that neither of us would recommend old style &sub() over just sub() for new code.

      I didn't explain var passing very well, fair enough. I can write an article about this if there is enough interest. There are limits to what can be explained in a short post. And there are some extremely complex things that have to do with this. But yeah, in general when you call a sub, you push things onto a stack and the sub consumes them by shifting them off the stack, just like with any other main programming language, C, C++, JAVA, etc. Yes, there are things that are different things about say how C and C++ and Perl does this, but these are details. The basic "model" about how to send stuff to a sub and get stuff back is the same.

        I don't think that there are any at all.

        See warnings.

        Strict is a compile time thing - not run time.

        The strict documentation disagrees:

        "strict refs" ... generates a runtime error if you use symbolic references (see perlref).
        Scoping like "my vars" is a big part of what "use strict" enforces....

        As I wrote in my previous message, you can avoid lexical variables altogether (and avoid lexical scoping altogether) and satisfy strict. Did you try it? You can also declare all of your lexical variables at package-level scope and satisfy strict. strict has nothing to do with scoping (except that strict's area of effect is lexical).

        ... in general when you call a sub, you push things onto a stack and the sub consumes them by shifting them off the stack, just like with any other main programming language....

        I can think of multiple machines -- virtual and otherwise -- where that's not true.

        #!/usr/bin/perl -- my $f = undef; print "$f\n"; use warnings; print "$f\n"; no warnings; print "$f\n"; __END__ Use of uninitialized value in concatenation (.) or string at - line 7.