PerlingTheUK has asked for the wisdom of the Perl Monks concerning the following question:

Dear Monks, I am currently writing a function, which uses a subfunction. It looks a bit like this:
sub my_func{ my ( $self, $ptr_array, $value ) = @_; return look_right() if ( $value == 0 ); return look_left() if ( $value == @{ $ptr_array } ); return ( look_right() && look_left() ); sub look_right() {... [uses $value and $ptr_array] } sub look_left() {... [uses $value and $ptr_array] } }
To my understanding of localisation, all "my" variables shouldd be available within the encapsulated subs. Yet I get an error saying they will not stay shared. Why is that? what do I need to do?
What is this warning for? I understand I can disable it but what does it really want to tell me? I am just suspicious there is something that I dont expect happening which I cannot see.

Cheers,
PerlingTheUK

Replies are listed 'Best First'.
Re: My Confusion
by borisz (Canon) on Sep 08, 2004 at 12:53 UTC
    thats because your subs inside subs are named. Try unnamed closures and it works fine. The reason is that the vars inside your named functions have a own live.
    sub my_func{ my ( $self, $ptr_array, $value ) = @_; my $look_right = sub {... [uses $value and $ptr_array] } my $look_left = sub {... [uses $value and $ptr_array] } return $look_right->() if ( $value == 0 ); return $look_left->() if ( $value == @{ $ptr_array } ); return ( $look_right->() && $look_left->() ); }
    Boris
      That works fine. Thank you.

      PerlingTheUK
Re: My Confusion
by Fletch (Bishop) on Sep 08, 2004 at 13:02 UTC
Re: Nested subroutines and access to variables in an outer scope
by Aristotle (Chancellor) on Sep 08, 2004 at 21:15 UTC

    Perl is not Pascal. :-) Nested functions are syntactically possible, but not really supported as a style of coding. The solution borisz gave works, but you instantiate two new closures every time the function is called — a lot of wasted effort.

    Why don't you simply write utility functions and pass the parameters out to them?

    sub my_func { my ( $self, $ptr_array, $value ) = @_; return look_right( $ptr_array, $value ) if ( $value == 0 ); return look_left( $ptr_array, $value ) if ( $value == @{ $ptr_arr +ay } ); return ( look_right( $ptr_array, $value ) && look_left( $ptr_array, $value ) ); } sub look_left { my ( $ptr_array, $value ) = @_; # ... } sub look_right { my ( $ptr_array, $value ) = @_; # ... }

    The other alternative, if for some reason you really don't want to pass parameters, would be to use a naked block to share the variables among functions:

    { my ( $ptr_array, $value ); sub my_func { my $self; ( $self, $ptr_array, $value ) = @_; return look_right() if ( $value == 0 ); return look_left() if ( $value == @{ $ptr_array } ); return ( look_right() && look_left() ); } sub look_left { ... } sub look_right { ... } }

    One side comment: please don't use prototypes unless there's a real reason to. Of which there are very few, none of which the code you show is indicative of. For your own benefit, please read Far More Than Everything You've Ever Wanted to Know about Prototypes in Perl.

    Makeshifts last the longest.

      Just a bit of nit picking, but moving the vars out of the scope of my_func makes it impossible to call my_func recursive.
      Boris