Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>I don't quite get what you are trying, but you can always make your subs pluggable:</p> <p>We have a sub <code>process_file</code>. It takes a subroutine as argument that will do the main processing:</p> <pre><code>our $counter; sub process_file { my ($subroutine, @args) = @_; local $counter = get_counter(); my @return_value = $subroutine-&gt;(@args); set_counter($counter); return @return_value; } # Here are other sub definitions for the main processing # They can see $counter and always magically have the right value. # If they assign to it, the counter file will be updated afterwards. </code></pre> <p>Assuming we have a sub <code>process_type_A</code>, we can then do</p> <pre><code>my @return_values = process_file(\&amp;process_type_A, $arg1, $arg2, $arg3); </code></pre> <p>This behaves just like <code>process_type_A($arg1, $arg2, $arg3)</code>, except for the extra call stack frame and the <code>$counter</code> setting.</p> <p>If you prefer passing names instead of coderefs, we can arrange for that too.</p> <pre><code>package MitchelWB::FileParsingLib; our $counter; our %file_type_processing_hash = ( "typeA" =&gt; \&amp;process_type_A, "typeB" =&gt; \&amp;process_type_B, "countLines" =&gt; sub { # anonymous sub open my $fh, '&lt;', "./dir/$counter.txt" or die "cant open $counter file"; my $lines = 0; $lines++ while &lt;$fh&gt;; return $lines; }, ); sub process_file { my ($filetype, @args) = @_; local $counter = get_counter(); # fetch appropriate subroutine: my $subroutine = $file_type_processing_hash{$filetype}; die "$filetype is not registered" if not defined $subroutine; # check for existence die "$filetype is not assigned to a sub" if ref $subroutine ne 'CODE'; # check that we have a sub # execute my @return_value = $subroutine-&gt;(@args); set_counter($counter); return @return_value; } ...; my $num_of_lines = process_file('countLines'); </code></pre> <hr> <h2>Edit: The Most Elegant Solution</h2> <h3>or: Attributes are really neat</h3> <p>Why stupid callbacks? Why extra code? Why calling conventions? Why dispatch tables? While they all are very interesting and flexible, there is a more elegant solution. I had just forgotten a tiny little piece of information, but now it has all fallen into place. Perl has "Attributes", known as "Annotations" in other languages, that allow us to, well, annotate code or variables.</p> <p>Defining a new Perl attribute is easy. We <code>use Attribute::Handlers</code> and define a sub with the same name as the attribute you want to use:</p> <pre><code>sub file_processor :ATTR(CODE) { my (undef, $glob, $subroutine) = @_; no strict 'refs'; ${$glob} = sub { local $counter = get_counter(); my @return_value = $subroutine-&gt;(@_); set_counter($counter); return @return_value; } </code></pre> <p>We use the attribute <code>:ATTR(CODE)</code> to denote that this is a attribute applicable for subroutines. We only need two arguments, the full name of the subroutine we want to annotate, and a coderef to the sub.</p> <p>We then turn off a part of the strictness to redefine the sub with <code>${$glob}</code>. This is a bit advanced, but it essentially just accesses the internal symbol table.</p> <p>We replace the annotated sub with a dumbed-down version of <code>process_file</code> as given above. We can pass all arguments (<code>@_</code>) right through without further processing.</p> <p>After all that, we add a tiny litte piece of information to the subs you used before:</p> <pre><code>sub process_type_A :file_processor { print "I can haz $counter\n"; } </code></pre> <p>… and it just does the replacement without further modifications. The changes are invisible when using the library. I am aware of the restrictions of this approach, but you are unlikely to run into them when writing ordinary code.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload