Beefy Boxes and Bandwidth Generously Provided by pair Networks
Syntactic Confectionery Delight
 
PerlMonks  

File::Rsync output functions and global variables

by robartes (Priest)
on Oct 08, 2003 at 18:31 UTC ( [id://297686]=perlquestion: print w/replies, xml ) Need Help??

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

I'm writing a module that uses File::Rsync, which has an option to capture the output from rsync through subrefs. From the docs:
The outfun and errfun options take a function reference. The function is called once for each line of output from the rsync program with the output line passed in as the first argument, the second arg is either 'out' or 'err' depending on the source. This makes it possible to use the same function for both and still determine where the output came from.

This is fine if you want to write the output to a log file or some such thing, but if you want to capture the output into a variable, you pretty much have to make it global. Something like:

package MyModule; use File::Rsync; my %rsync_out; my $rsync=File::Rsync->new( { outfun => &rsync_out, errfun => &rsync_out, } ); ... sub rsync_out { my ($message, $type)=shift; $rsync_out{$type}.="$message\n"; }

That should work, but it uses a global variable that is set somewhere downstream in the script in a subroutine, so it is somewhat ugly.

I have a sneaky feeling that something can be done here with references and closures, but I'm drawing a blank as to what exactly.

So, what's the monks' opinion: is this a tolerable use of a global variable or should I try to be clever and avoid the global (suggestions as to what exactly 'clever' means in this case are welcome :) )? Personally, I'm inclined to go with the global var, for the sake of simplicity and maintainability.

CU
Robartes-

Replies are listed 'Best First'.
Re: File::Rsync output functions and global variables
by sandfly (Beadle) on Oct 08, 2003 at 21:07 UTC
    What you've done is perfectly acceptable. You have used 'my' to declare the output variable, so it isn't global, it's lexically scoped. In the example above, it is only visible to code within the file you declare it in.

    If you need to limit the scope further, you can put braces around the code which needs to see it.

    package MyModule; use File::Rsync; my $rsync; { my %rsync_out; $rsync=File::Rsync->new( { outfun => &rsync_out, errfun => &rsync_out, } ); sub rsync_out { my ($message, $type)=shift; $rsync_out{$type}.="$message\n"; } sub outmsg { $rsync_out{out} } sub errmsg { $rsync_out{err} } } # ... # code here has no clue about %rsync_out # (but it can still see $rsync because I declared # it outside the braces.) # ... # Access the output using the outmsg and errmsg subs my $output = outmsg;

    The code not tested. In most cases, you don't need to bother with this anyway.

      > In most cases, you don't need to bother with this anyway.
      I mean you don't need to bother with the braces - you do have to test!
Re: File::Rsync output functions and global variables
by robartes (Priest) on Oct 08, 2003 at 19:55 UTC
    Well, it is supposed to be an example script that will not run, but it should at least be correct. So:
    package MyModule; use File::Rsync; my %rsync_out; my $rsync=File::Rsync->new( { outfun => \&rsync_out, errfun => \&rsync_out, } ); ... sub rsync_out { my ($message, $type)=@_; $rsync_out{$type}.="$message\n"; }

    CU
    Robartes-

Re: File::Rsync output functions and global variables
by tilly (Archbishop) on Oct 12, 2003 at 02:44 UTC
    You can indeed play games with references closures. Here is a solution that does both:
    package MyModule; use File::Rsync; # In some local scope my $rsync = File::Rsync->new({ outfun => bind_args(\&capture_messages, \ my $out), errfun => bind_args(\&capture_messages, \ my $err), }); # Somewhere else sub capture_messages { my ($string_ref, $message, $type) = @_; $$string_ref .= $message . "\n"; } sub bind_args { my ($func, @args) = @_; sub {$func->(@args, @_)}; }
    A bit sophisticated, but now the output is captured in a variable that is local to wherever your rsync declaration is done.

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others pondering the Monastery: (2)
As of 2024-04-19 01:53 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found