in reply to Re: "Biochem BINGO" or "Noob Seeks Zen Thrashing"
in thread "Biochem BINGO" or "Noob Seeks Zen Thrashing"

QM! Thanks so much!

It'll take a while to digest all of your feedback, but there is one thing that leaps out:

I couldn't figure out how to pass a nested subroutine. This is adapted from the Perl Cookbook: (and one of the beginner-gotchas that got me):

sub outloop { #NOOB GOTCHA my $k = "string"; sub inside { return $k."cheese" } return inside( ); }
So I thought I had to do this, without figuring out how to use references (or restructure the whole thing):
sub outer { #APPARENTLY CORRECT my $k = "string"; local *inside = sub { return $k."cheese" }; return inside( ); }

ry

"I'm not afraid of Al Quaeda. I'm afraid of Al Cracker." -Chris Rock

Replies are listed 'Best First'.
Re^3: "Biochem BINGO" or "Noob Seeks Zen Thrashing"
by QM (Parson) on Dec 12, 2005 at 23:10 UTC
    I couldn't figure out how to pass a nested subroutine.
    "pass" a sub? You didn't pass a sub. You defined it, then used it, then returned it's return value. If you want to pass a sub, you need a reference to it. Off the top of my head, there are 2 easy ways:

    1) Define an anonymous (no-name) sub, and assign it to a scalar ref

    my $square_this = sub { my $x = shift; return $x**2; };
    2) Take a reference to a named sub
    sub square { my $x = shift; return $x**2; } my $square_this = \□
    Use it like this (either version):
    my $squared = $square_this->($hypotenuse);
    Perhaps what you really meant was nested sub, in the Pascal sense. In Perl there's no such animal per se, though it can be emulated. In Perl we could talk about a limited scope sub, only available to a certain sub or collection of subs. Again, a couple of ways:

    1) Packages: define a package to limit scope

    package Square; sub square { my $x = shift; return $x**2; }
    Use it one of these ways:
    1) Inside package Square (perhaps by other routines in that package)
    my $squared = square($hypotenuse);
    2) Outside of package Square, e.g., main:
    my $squared = Square::square($hypotenuse);
    3) If you do this, it won't be limited in scope.
    Package Square is in Square.pm, the following is in main:
    use Square qw(square); my $squared = square($hypotenuse);
    The solution I think you're looking for (and tell me if I'm wrong), is a closure with an anonymous sub, that can only be seen by your named sub. For instance:
    { # closure for cubed my $square = sub { my $x = shift; return $x**2; }; sub cubed { my $z = shift; return $z*$square->($z); } } # end closure for cubed
    Now only the subs (and other code) in the closure can see $square (unless you give out a reference to it).

    -QM
    --
    Quantum Mechanics: The dreams stuff is made of