Beefy Boxes and Bandwidth Generously Provided by pair Networks
XP is just a number

preserve array from getting re-initilize

by tart (Beadle)
on Jul 15, 2010 at 02:55 UTC ( #849681=perlquestion: print w/replies, xml ) Need Help??

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

In below code I am preserving the @verbose so that It
won't get altered or re-initilized, To avoid global variable I am using
this method.

Is there any alternative (better)way to do this?
Any suggestion?
{ my @verbose; sub verbose { my $configHR = shift; my $info = shift; return \@verbose if($info eq 'verbose'); my $time = scalar localtime(); $time =~ /(\d\d:\d\d:\d\d)/; $time = $1; push(@verbose, "\n$time : [$info]\n"); if(length($info) > 55) { $info =~ s/(.{1,50})/$1-]\n\t [-/; } return unless($configHR->{VERBOSE}); print "$time [$info]\n"; } }

Replies are listed 'Best First'.
Re: preserve array from getting re-initilize
by ikegami (Pope) on Jul 15, 2010 at 03:04 UTC

    That's perfectly fine. You could also use state, but I prefer the above.

    [ hum, [doc://state] doesn't work. ]

      [doc://perlfunc#state-EXPR|state] and [doc://perlfunc#state-EXPR] also work as make-dos: state and state EXPR.
Re: preserve array from getting re-initilize
by TomDLux (Vicar) on Jul 15, 2010 at 04:58 UTC

    It's called a closure, and it's perfectly valid way of doing things, though 'state' is the new, improved way.

    But I'm confused by what this routine is supposed to do. Considering you print out the time and message, if $configHR->{VERBOSE} is true, I'm guessing this is a logging routine.

    But you've rather overloaded the term verbose ... It's the name of the routine, the tag of the only postion of the config hashref you look at, and a value for the info field.

    Personally, I would go for a small inline package named logger' witha constructor, a print() method and a flush() method. The constructor takes and arg, 'mode', and sets a 'cached' attribute if mode is 'cached'. print() caches the formatted message is caching is enabled, otherwise prints it.

    use POSIX qw(strftime); my $time = POSIX::strftime( "%T", localtime)

    will give you the hours, minutes seconds. As for truncating the message

    my $msg = substr( $msg, 0, 50 ) . '-' if 50 < length $msg;

    If you wanted to be fancy, the constructor could return a caching subclass or a printing subclass instance, depending on the arg. But a single if() is not too painful.


Re: preserve array from getting re-initilize
by jwkrahn (Monsignor) on Jul 15, 2010 at 04:53 UTC
    return \@verbose if($info eq 'verbose');

    You are returning a reference to the array @verbose so your array could be altered or re-initilized outside this subroutine.

    my $time = scalar localtime(); $time =~ /(\d\d:\d\d:\d\d)/; $time = $1;

    That is usually written as:

    my $time = sprintf '%02d:%02d:%02d', ( localtime )[ 2,1,0 ];
Re: preserve array from getting re-initilize
by FunkyMonk (Chancellor) on Jul 15, 2010 at 09:40 UTC
    What you've done is fine, but I'm posting to comment on the other advice you've been given: use a state variable.

    Unfortunately, non-scalar state variables are pretty much broken. Consider:

    foo(); sub foo { state @verbose = 1..10; say shift @$verbose; }

    gives an Initialization of state variables in list context currently forbidden error.

    However, there are work-arounds, such as:

    foo(); foo(); foo(); sub foo { state $verbose = [1..10]; say shift @$verbose; } __END__ 1 2 3

    Using diagnostics states that "Constructions such as state (@a) = foo() will be supported in a future perl release".

Re: preserve array from getting re-initilize
by NetWallah (Canon) on Jul 15, 2010 at 04:30 UTC
    Here is an alternative, using OO technology to obtain the encapsulation (among other things):
    use strict; use warnings; { package SomeThing; my @verbose; sub new{ my ($class,%params) = @_; return bless {%params, }, $class; } sub get_info{ my ($self) = @_; return \@verbose; } sub insert{ my ($self,$opt,$info)=@_; push @verbose, "\n" . (my $time = ((scalar localtime)=~/(\d\d:\d\d:\d\d)/)[0]) . " \[$info]\n"; return unless $opt->{VERBOSE}; if(length($info) > 55){ $info =~ s/(.{1,50})/$1-]\n\t [-/; } print "$time [$info]\n"; } } my $obj = new SomeThing(color=>"Blue"); $obj->insert ({VERBOSE=>1}, "This text"); $obj->insert ({VERBOSE=>1}, "That text"); print $_ for @{ $obj->get_info()};

         Syntactic sugar causes cancer of the semicolon.        --Alan Perlis

Re: preserve array from getting re-initilize
by TedPride (Priest) on Jul 15, 2010 at 03:16 UTC
    Works perfectly fine, it's the method I use as well. Only I do it like:
    { my @verbose; sub verbose { ... }}
    No need to have that messy indenting or extra lines in there.

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://849681]
Approved by ikegami
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others having an uproarious good time at the Monastery: (3)
As of 2021-05-13 10:46 GMT
Find Nodes?
    Voting Booth?
    Perl 7 will be out ...

    Results (134 votes). Check out past polls.