Beefy Boxes and Bandwidth Generously Provided by pair Networks
Your skill will accomplish
what the force of many cannot
 
PerlMonks  

Need an $a and $b as in perl's sort routine

by rational_icthus (Sexton)
on Jan 10, 2006 at 23:15 UTC ( [id://522347]=perlquestion: print w/replies, xml ) Need Help??

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

I'm working on a perl module here at work for a reporting system we're developing. I'd like to be able to pass in a text file for parsing and munging, and programatically specify what to do as follows:
# Handles initial parse (gets field # names from first line of 'file.out' my $file = ParseFile('file.out'); # Specifies fields on which to subtotal $file->keys = qw( Cust_Grp Order_Date Item Name ); # Adds a field $file->field('Line_Total', sub { $row->{Unit_Price}*$row->{Qty} }); ... # Process file $file->process();
The '$file->field(...)' line allows me to dynamically add columns to the report based on existing data. I can't hard code the new column definitions, as this code needs to be somewhat abstract. For that reason, I'm using an anonymous sub to define the value of the field. As the file processor runs, each line will add a column to the report by running that sub, pulling values from that report line. I'd like the '$row' variable to be a hash reference filled with key/value pairs from the current line. I'd like it to be autopopulated in the sub, much like  sort {$a <=> $b} @list autopopulates the '$a' and '$b' in the code block there. Is there a way to do this? I've super searched on '$a $b', etc., but too many results are kicking out since those variables are often used as temp variables, etc. Any help would be appreciated. Thanks.

Replies are listed 'Best First'.
Re: Need an $a and $b as in perl's sort routine
by demerphq (Chancellor) on Jan 10, 2006 at 23:22 UTC

    Use dynamic variables. And then localize them in the sub doing the calling. Using variables names that start with :: will force them into main.

    sub exec_callback { my $code=shift; local $::hash={}; local $::row=1; $code->(); }

    This is basically all that happens with $_ or $a and $b in a sort routine or map or File::Find or Scalar::List::Utils. $a and $b are declared "special" so there shouldnt be any conflicts with them. Using $main::hash ($::hash) might have the potential for conflict.

    ---
    $world=~s/war/peace/g

      Wouldn't doing a local $::row={} leave '$row' defined in main even outside the code block, however? I'd like $row to disappear once the instruction is complete.

        No it wouldn't. Or rather $::row would revert to whatever it was before you localized it once you exited the sub that contains the localization. In the example below i use a bare block instead of sub to demonstrate but the same thing applies.

        D:\dev\PM>perl -le"$::x='outer'; $c=sub{print $::x}; { local $::x='inn +er'; $c->() } $c->()" inner outer

        Thats the whole point of dynamic scoping...

        ---
        $world=~s/war/peace/g

      But then the code is not usable from a module, no?

      I have used things like the following in the past:

      sub exec_callback { my $code = shift; my $caller = caller; no strict 'refs'; no warnings 'once'; local(*{$caller."::a"}) = \my $a; local(*{$caller."::b"}) = \my $b; $a = {}; $b = 1; $code->(); }

      Good Day,
          Dean

        But then the code is not usable from a module, no?

        A fully qualified global name is always accessable and usable from everywhere. The "problem" I think you are indirectly referring to is when you have a module X that uses globals that exist within the package that other code must then fully qualify using the full package name. For a variable named $X::x thats not so bad, but when the package is Some::Long::Package::Name it starts getting clumsy.

        The options are to export the globals in to the consumers package or to use "special globals" (like $a, $b, and $_) or to just use vars in package main. Assuming that you don't have a lot of globals in use in package main (IME a safe assumption) using such vars is IMO a reasonable choice. In other words typing $::Hash isn't so tough. Typing $Some::Long::Package::Name::Hash is.

        ---
        $world=~s/war/peace/g

Re: Need an $a and $b as in perl's sort routine
by ysth (Canon) on Jan 10, 2006 at 23:20 UTC
Re: Need an $a and $b as in perl's sort routine
by simonm (Vicar) on Jan 11, 2006 at 00:57 UTC
    If you only have one implicit target variable, use the variable that's already been set aside for implicit targets -- $_.

    It's easy to local $_ before calling the sub, and with $_ everyone will know what you're doing.

Log In?
Username:
Password:

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

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

    No recent polls found