Beefy Boxes and Bandwidth Generously Provided by pair Networks
P is for Practical

Determine if sub is called from control block.

by shotgunefx (Parson)
on Feb 26, 2002 at 22:35 UTC ( #147752=perlquestion: print w/replies, xml ) Need Help??
shotgunefx has asked for the wisdom of the Perl Monks concerning the following question:

Is there a way to determine what type of block a sub is called from?

I was working on a greplike operator called findone.

It needs to keep track of where it was called from to keep it's position in the @array in question.
while ( my ($val,$index) = findone { $_ > 1000 } @elements){ # Do something }

This work find and dandy until I realized a subtle bug.
my @tokens = (tokens here); while ($line =<>){ chomp($line); die "$line is not a valid token" unless findone { m/^$line/ } @tok +ens; }
Because it keeps track of where and what it's called with, it will never match past the first match which means it will fail on the second block. (Unless there are multiple matches in @tokens. Then it will fail on the N+1 iteration.)
If I move my @tokens into the while block, it will work ok because the ref is different which it will see.

I knowning about this could just take care not to do this, or I could make a version that doesn't keep track and call it find or findfirst / findany whatever, but in the spirit of DWIM and learning, is there a way to tell if it's being called from a control block? I realize this wouldn't help calls within bare blocks.
I have a feeling I could coke up something with a source filter but would like to avoid it if possible.



"To be civilized is to deny one's nature."

Replies are listed 'Best First'.
Re: Determine if sub is called from control block.
by lordsuess (Scribe) on Feb 27, 2002 at 11:24 UTC
    With caller, you can find out about the line this sub was called. If you write a __DATA__ at the end of the script, you can use a seek(DATA, 0, 0) to jump at the beginning of the script or seek(DATA, 0, $offset) to jump to a certain line. Then just search for the surrounding { } and the logical statements.

    As another solution that might also work with several files, you can find the Filename of the code which called your sub with caller, open the file and do about the same as above. The latter might be cleaner, but in the moment I can't find a better solution...

      You can do so even without using DATA, which only seems to work for a single file or the like... just use an open on the Filename caller gave you, jump into the right line caller gave you and scan around a bit :-)

      Best regards,
      perl -le "s==*F=e=>y~\*martinF~stronat~=>s~[^\w]~~g=>chop,print"

        Interesting idea. Thanks!


        "To be civilized is to deny one's nature."
      Pretty Clever! Never played much with DATA. Unfortunately, it won't work as I want this as a module. I think trying to do that on the fly will cause many problems. (Evals, etc)

      I actually just finished a version using Filter::Simple (Changes the calls if the line doesn't contain a for/foreach/while that works but I'd like to avoid requiring it if I can.



      "To be civilized is to deny one's nature."
Re: Determine if sub is called from control block.
by lordsuess (Scribe) on Feb 27, 2002 at 09:58 UTC
    I'm not sure if I understood your problem correctly; maybe the built-in function caller might help you to find out where you came from.

    Just have a look at perldoc -f caller

      Thank for the suggestion, but caller doesnt' provide the context info I need. I'm already using it for the code in question. I'm basically trying to find out wether it's being called in a loop construct or not. (The code keeps track of it's own state info without any OO stuff or direction from the user.)

      I've re-written it to use Filter::Simple to change any calls that are not part of a while/for/foreach to use a different version that doesn't retain state. I'll be posting it soon.


      "To be civilized is to deny one's nature."
Re: Determine if sub is called from control block.
by shotgunefx (Parson) on Feb 27, 2002 at 03:13 UTC
    Seeing I can't edit a root node, that would be "I knowing" and "cook up" not "coke up". Sorry for the typos.


    "To be civilized is to deny one's nature."

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://147752]
Approved by root
[Corion]: :-D Perl is everywhere!
[choroba]: Discipulus: Ha! Sane dot award 2016!

How do I use this? | Other CB clients
Other Users?
Others wandering the Monastery: (7)
As of 2017-01-20 10:40 GMT
Find Nodes?
    Voting Booth?
    Do you watch meteor showers?

    Results (174 votes). Check out past polls.