Beefy Boxes and Bandwidth Generously Provided by pair Networks
Clear questions and runnable code
get the best and fastest answer
 
PerlMonks  

Recover a variable from a function

by Chaoui05 (Scribe)
on May 19, 2016 at 07:14 UTC ( [id://1163428]=perlquestion: print w/replies, xml ) Need Help??

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

Hi monks ! Iam beginner and i have a simple question. I hope it's not too easy. How to recover a variable value from a function to another in Perl I have my variable "$start" whose i would like to recover the value in the second.
sub Start_timer : Test(startup) { my $start = time(); cprint "#\x037Started at ", (strftime '%A %d %B %Y %H:%M:%S',localti +me($start)), "\x030\n"; } sub End_timer : Test(shutdown) { #my $start; my $end = time; cprint "#\x037Ended at ", (strftime '%A %d %B %Y %H:%M:%S', localtim +e($end)),"\x030\n"; cprintf "#\x035 Total run time=>", $end-$start, " seconds\n"; cprintf ("%02d:%02d:%02d\x030\n",(gmtime($end-$start))[2,1,0]); }
Many Thanks !!

Replies are listed 'Best First'.
Re: Recover a variable from a function
by Ovid (Cardinal) on May 19, 2016 at 10:32 UTC

    It looks like you're using Test::Class. That module is specifically designed to handle situations like this. In particular, every method is called with an invocant which in this case is a blessed, empty hashref. You're allowed (even encouraged!) to shove things in that hashref. For test classes, I like to call my invocant $test instead of the standard $self.

    sub Start_timer : Test(startup) { my $test = shift; my $start = time(); cprint "#\x037Started at ", (strftime '%A %d %B %Y %H:%M:%S',localti +me($start)), "\x030\n"; $test->{start} = $start; } sub End_timer : Test(shutdown) { my $test = shift; my $start = $test->{start}; my $end = time; cprint "#\x037Ended at ", (strftime '%A %d %B %Y %H:%M:%S', localtim +e($end)),"\x030\n"; cprintf "#\x035 Total run time=>", $end-$start, " seconds\n"; cprintf ("%02d:%02d:%02d\x030\n",(gmtime($end-$start))[2,1,0]); }

    However, this is a practice I discourage. First, it's easy to write something like $test->{strat}; and wonder why you didn't get a value. Second, encouraging people to reach inside of objects like that is generally a bad idea.

    Another solution would be to look at Test::Class::Moose and use proper attributes.

    has 'start' => ( is => 'ro', isa => 'Int', default => sub { return time }, ); sub test_startup { my $test = shift; my $start = $test->start; cprint "#\x037Started at ", (strftime '%A %d %B %Y %H:%M:%S',localti +me($start)), "\x030\n"; } sub test_shutdown { my $test = shift; my $start = $test->start; my $end = time; cprint "#\x037Ended at ", (strftime '%A %d %B %Y %H:%M:%S', localtim +e($end)),"\x030\n"; cprintf "#\x035 Total run time=>", $end-$start, " seconds\n"; cprintf ("%02d:%02d:%02d\x030\n",(gmtime($end-$start))[2,1,0]); }

    Also, it's a bit out of date, but you might want to read my Test::Class tutorial. It's in five parts, but it's worth the effort.

      Thanks for the comment. yes , in fact , Test::Class seems to allow that. I used native Perl code to do differently and because it was the first thing i thought. But i retain this approach.
Re: Recover a variable from a function
by Corion (Patriarch) on May 19, 2016 at 07:24 UTC

    The simplest approach is to not use a lexical variable but a global variable:

    use vars '$start'; sub Start_timer : Test(startup) { $start = time; ... }; sub End_timer : Test(shutdown) { print time - $start; ... }

    If you really want to avoid global variables for things like that, you could use the state keyword and a function to read the start time:

    sub get_or_init_start_time { state $start ||= time; }

    You need to call this function in two places, once to initialize the $time variable and once to retrieve the value.

      Thanks Corion ! I have to use also global variables instead of lexical variables.
      I did that easily but it doesn't work:
      use vars '$start'; sub Start_timer : Test(startup) { my $start = time(); cprint "#\x037Started at ", (strftime '%A %d %B %Y %H:%M:%S',localti +me($start)), "\x030\n"; } sub End_timer : Test(shutdown) { print time - $start; my $end = time; cprint "#\x037Ended at ", (strftime '%A %d %B %Y %H:%M:%S', localtim +e($end)),"\x030\n"; cprintf "#\x035 Total run time=>", $end-$start, " seconds\n"; cprintf ("%02d:%02d:%02d\x030\n",(gmtime($end-$start))[2,1,0]); }
      And i have this following issue in my shell :
      ok 243 - Logout ok Use of uninitialized value $MyTest::start in subtraction (-) at MyTest +.pm line 402. 1463646157#Ended at jeudi 19 mai 2016 10:22:37 Use of uninitialized value $MyTest::start in subtraction (-) at MyTest +ingSuite.pm line 407. # Total run time=>Use of uninitialized value $MyTest::start in subtrac +tion (-) at MyTest.pm line 408. 08:22:37
Re: Recover a variable from a function
by haukex (Archbishop) on May 19, 2016 at 07:35 UTC

    Hi Chaoui05,

    One approach, which avoids directly manipulating a global, is to pass around a "context" (a term/concept commonly used e.g. in Java), basically a data structure that holds state information that would normally be stored in globals. The advantage is you can have multiple contexts at the same time, and at least in Java context objects are often thread-safe, serializable containers for what essentially are global variables. The following approach has similarities to an OO approach (you could imagine the subs in the example being methods on an object which holds the state), but the difference is that a context data structure is independent of the functions/methods that use it - it's often an object of its own (although in this example I've just used a hashref). Implementing such a "context" data structure to replace globals can be a good first step in modularizing a legacy script.

    use warnings; use strict; my $ctx = {}; run($ctx); stop($ctx); stats($ctx); sub run { my ($ctx) = @_; $ctx->{start} = time; sleep 2; } sub stop { my ($ctx) = @_; $ctx->{end} = time; } sub stats { my ($ctx) = @_; $ctx->{runtime} = $ctx->{end} - $ctx->{start}; print "Start: ".gmtime($ctx->{start})." UTC\n"; print " Stop: ".gmtime($ctx->{end})." UTC\n"; print " Time: ".$ctx->{runtime}." s\n"; } __END__ Start: Thu May 19 07:29:27 2016 UTC Stop: Thu May 19 07:29:29 2016 UTC Time: 2 s

    Hope this helps,
    -- Hauke D

    Update: Expanded description a bit.

      Ok i understand but it seems to be longer with your approach . Is it ?

        Hi Chaoui05,

        Yes, this approach is going to be a little more code - but only a few lines, depending on the specific case of course. However, as is often the case with such trade-offs, the little bit of time you spend writing a few more lines of code today may be much less than the time spent on debugging issues caused by misuse of global variables or the refactoring of the code as it grows more complex tomorrow.

        Hope this helps,
        -- Hauke D

Re: Recover a variable from a function
by Laurent_R (Canon) on May 19, 2016 at 09:41 UTC
    Hi Chaoui05,

    Another approach is to make the lexical variable accessible to the two subroutines where you need to access to it by enclosing the variable declaration and the sub definition in a common code block.

    { my $start; sub Start_timer : Test(startup) { $start = time(); cprint "#\x037Started at ", (strftime '%A %d %B %Y %H:%M:%S',lo +caltime($start)), "\x030\n"; } sub End_timer : Test(shutdown) { my $end = time; cprint "#\x037Ended at ", (strftime '%A %d %B %Y %H:%M:%S', loc +altime($end)),"\x030\n"; cprintf "#\x035 Total run time=>", $end-$start, " seconds\n"; cprintf ("%02d:%02d:%02d\x030\n",(gmtime($end-$start))[2,1,0]); } }
      Thanks Laurent !! Advantage (or disadvantage ) in Perl is that there are a lot of possibilities to do one thing ! Thanks againb for this another approach

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1163428]
Approved by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others about the Monastery: (3)
As of 2024-04-25 20:35 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found