Question about sub calling other sub

M

Martin Kissner

hello together,

I have a sub, which can be called by different other subs.
There are some slight differences depending from which sub it is called.
Is it possible to find out, which other sub called the actual sub?

I have writen the following script for demonstration:
Would it be possible to find out which sub called "who_called_me"
without passing the strings to it?

Best regards
Martin

-----
#!/usr/bin/perl

use warnings;
use strict;

one();

sub who_called_me {
my $who = shift;
print "$who called me\n";
}
sub one {
who_called_me("one");
}
sub two {
who_called_me("two");
}
 
D

Dr.Ruud

Martin Kissner schreef:
I have a sub, which can be called by different other subs.
There are some slight differences depending from which sub it is
called. Is it possible to find out, which other sub called the actual
sub?


A quick search on CPAN returned:
Sub::Caller
Devel::CallTrace

See also
http://gisle.aas.no/perl/illguts/



But why not change your code?
 
R

Randal L. Schwartz

Martin> I have a sub, which can be called by different other subs.
Martin> There are some slight differences depending from which sub it is called.
Martin> Is it possible to find out, which other sub called the actual sub?

Please, please don't do this. You are introducing fragility and instability in
your code by thinking this way.

If you want a subroutine to have different behaviors, pass it a flag argument
of some kind. But why not just create two different subroutines to call, so
the "flag" is effectively part of the subroutine name. Then factor out the
parts in common of those two subroutines to a new subroutine or two. Then you
have more reusable components, and a much better and clearer design.

print "Just another Perl hacker,"; # the original

--
Randal L. Schwartz - Stonehenge Consulting Services, Inc. - +1 503 777 0095
<[email protected]> <URL:http://www.stonehenge.com/merlyn/>
Perl/Unix/security consulting, Technical writing, Comedy, etc. etc.
See PerlTraining.Stonehenge.com for onsite and open-enrollment Perl training!
*** Free account sponsored by SecureIX.com ***
*** Encrypt your Internet usage with a free VPN account from http://www.SecureIX.com ***
 
M

Martin Kissner

Randal L. Schwartz wrote :
Martin> I have a sub, which can be called by different other subs.
Martin> There are some slight differences depending from which sub it is called.
Martin> Is it possible to find out, which other sub called the actual sub?

Please, please don't do this. You are introducing fragility and instability in
your code by thinking this way.

Thank you for your feedback.
I will gladly take advice from expierienced Perl programmers.
Still more gladly I would like to understand where the problem is or
how the fragility and instability could arise.
If you want a subroutine to have different behaviors, pass it a flag argument
of some kind.

This is what I have done now using a variable $action.
But why not just create two different subroutines to call, so
the "flag" is effectively part of the subroutine name. Then factor out the
parts in common of those two subroutines to a new subroutine or two. Then you
have more reusable components, and a much better and clearer design.

I am very interested in learning to improve my code design.
In this case the differences are so small that I feel it would be better
to have only one sub. Else I'd feel like using two different tools for
driving screws *in* and *out* ;-)

Actually when I started I had three very simliar looking subs which I
now put together into one. By passing flags ($action) I trigger what
they are supposed to do.

Best regards
Martin
 
M

Martin Kissner

Christian Winter wrote :
See "perldoc -f caller".
The fourth element in the list returned by caller(EXPR) is
the complete name of the invoking sub, including the package
name, so in this case you will get back main::eek:ne and
main::two.

Thank you.
This looks like the solution I was looking for. Good to know.
Nevertheless I have decided to stick with the flags version for now.

Thanks also to Dr.Ruud for the feedback.

Best regards
Martin
 
A

Anno Siegel

Martin Kissner said:
Randal L. Schwartz wrote :

Thank you for your feedback.
I will gladly take advice from expierienced Perl programmers.
Still more gladly I would like to understand where the problem is or
how the fragility and instability could arise.


This is what I have done now using a variable $action.


I am very interested in learning to improve my code design.
In this case the differences are so small that I feel it would be better
to have only one sub. Else I'd feel like using two different tools for
driving screws *in* and *out* ;-)

Actually when I started I had three very simliar looking subs which I
now put together into one. By passing flags ($action) I trigger what
they are supposed to do.

The flag mechanism is sometimes used to avoid code duplication. In general,
I'd go with Randal and try to factor out the common part(s). "In a good
program, every routine does almost nothing". Sometimes different tools
for screwing a particular kind of screw in and out is a good solution.

But don't use the caller instead of an explicit flag. You create a
dependency that doesn't have to be there. There may be reasons to
call the subs from other packages, or to rename the packages that are
calling them. In both cases, the basically unrelated subs must be
changed. With the other solutions, (flag or part of the sub name)
everything happens at the place of call.

Anno
 
X

xhoster

The flag mechanism is sometimes used to avoid code duplication. In
general, I'd go with Randal and try to factor out the common part(s).
"In a good program, every routine does almost nothing".

I can't say I agree with that. If each sub does almost nothing, i.e. no
more or even less than a simple perl expression does, there is little point
in having them.
Sometimes
different tools for screwing a particular kind of screw in and out is a
good solution.

But don't use the caller instead of an explicit flag. You create a
dependency that doesn't have to be there. There may be reasons to
call the subs from other packages, or to rename the packages that are
calling them. In both cases, the basically unrelated subs must be
changed.

That I agree with.

Xho
 
A

Anno Siegel

I can't say I agree with that. If each sub does almost nothing, i.e. no
more or even less than a simple perl expression does, there is little point
in having them.

If the perl expression involves calling other do-almost-nothing
routines, who may again call others, the end result can be some
quite complex processing you don't want to expand every time you
call it.

Like all such sayings, especially when quoted without context, this must
be taken with a grain of salt. I don't remember where I read that
sentence, but I do remember that "routine" was defined as "any sequence
of statements that solve a particular problem", so a single sub could
consist of more than one routine in this sense. It is also language
dependent. Well-written FORTH programs often consist of lots of tiny
routines (in the strict sense of user-defined named functions). The
main problem with that is coming up with reasonable names for all the
stuff.

It can happen in Perl too. Here is an example of a set of benchmark
timing routines each one of which does almost nothing:

#!/usr/bin/perl
use strict; use warnings; $| = 1;

start_timing( my $coll_cpu);
1 for 1 .. 1_000_000;
print break_timing( $coll_cpu), " s cpu time\n";

resume_timing( $coll_cpu);
1 for 1 .. 1_000_000;
print break_timing( $coll_cpu), " s cpu time\n";

######################################################################

sub start_timing { resume_timing( $_[ 0] = 0) }
sub resume_timing { $_[ 0] -= cpu() }
sub break_timing { $_[ 0] += cpu() }
sub cpu { return $_->[ 0] + $_->[ 1] for [ times] }
__END__

Anno
 
M

Martin Kissner

Anno Siegel wrote :
The flag mechanism is sometimes used to avoid code duplication. In general,
I'd go with Randal and try to factor out the common part(s). "In a good
program, every routine does almost nothing". Sometimes different tools
for screwing a particular kind of screw in and out is a good solution.

But don't use the caller instead of an explicit flag. You create a
dependency that doesn't have to be there. There may be reasons to
call the subs from other packages, or to rename the packages that are
calling them. In both cases, the basically unrelated subs must be
changed. With the other solutions, (flag or part of the sub name)
everything happens at the place of call.

Thank you for your feedback, Anno.
Your comment has been quite helpful. I had to think about it for a few
days an while going ahead with my script I think I was able to improve
the code design keeping your advice in mind.

Best regards
Martin
 

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,969
Messages
2,570,161
Members
46,710
Latest member
bernietqt

Latest Threads

Top