Thanks to all those who offered help! Your suggestions helped me find a better solution.
use B::Deparse;
# make deparsing object
$deparse = B::Deparse->new("-p", "-sC");
# forward encoding transforms
@fwd = (
sub {$_[0]/100, ($_[1] + 128)/255, ($_[2] + 128)/255},
sub {$_[0] * 256/25700, ($_[1] + 128) * 256/65535, ($_[2] + 128) *
+ 256/65535},
sub {$_[0]/100, ($_[1] + 128) * 256/65535, ($_[2] + 128) * 256/655
+35},
sub {@_},
sub {$_[0] + 116 * $_[1]/500, $_[0], $_[0] - 116 * $_[2]/200},
sub {$_[0]/100 + 116 * $_[1]/50000, $_[0]/100, $_[0]/100 - 116 * $
+_[2]/20000},
sub {@_},
sub {$_[0] * 0.4821, $_[1] * 0.5, $_[2] * 0.41245},
sub {$_[0] * 0.9642, $_[1], $_[2] * 0.8249},
sub {@_},
sub {$_[0] * 96.42, $_[1] * 100, $_[2] * 82.49},
);
# reverse encoding transforms
@rev = (
sub {$_[0] * 100, $_[1] * 255 - 128, $_[2] * 255 - 128},
sub {$_[0] * 25700/256, $_[1] * 65535/256 - 128, $_[2] * 65535/256
+ - 128},
sub {$_[0] * 100, $_[1] * 65535/256 - 128, $_[2] * 65535/256 - 128
+},
sub {@_},
sub {$_[1], 500 * ($_[0] - $_[1])/116, 200 * ($_[1] - $_[2])/116},
sub {$_[1] * 100, 50000 * ($_[0] - $_[1])/116, 20000 * ($_[1] - $_
+[2])/116},
sub {@_},
sub {$_[0]/0.4821, $_[1]/0.5, $_[2]/0.41245},
sub {$_[0]/0.9642, $_[1], $_[2]/0.8249},
sub {@_},
sub {$_[0]/96.42, $_[1]/100, $_[2]/82.49},
);
# CIELAB transforms
sub _x2L {($_[0] > 216/24389) ? 116 * $_[0]**(1/3) - 16 : $_[0] * 2438
+9/27}
sub _xyz2Lab {my $L = _x2L($_[1]); $L, (_x2L($_[0]) - $L) * 500/116, (
+$L - _x2L($_[2])) * 200/116}
sub _L2x {($_[0] > 8) ? (($_[0] + 16)/116)**3 : $_[0] * 27/24389}
sub _Lab2xyz {_L2x($_[0] + $_[1] * 116/500), _L2x($_[0]), _L2x($_[0] -
+ $_[2] * 116/200)}
# make example transform sequence array
@seq = ($rev[1], \&_Lab2xyz, $fwd[10]);
# make combined transform
# parameter: (array_of_code_references)
# returns: (code_reference)
sub combine {
# copy transform array
my @t = @_;
# initialize expression
my $expr = '@_';
# for each transform step
for my $i (0 .. $#t) {
# add to expression
$expr = "\$t[$i]->($expr)";
}
# return combined transform
eval("return(sub {$expr})");
}
# combined transform (fast and flexible, but requires initializaton (a
+pprox. 75 μs))
$trans3 = combine(@seq);
# deparse the code reference
$body = $deparse->coderef2text($trans3);
print "\$trans3: $body\n";
# call the transform
@out = &$trans3(@in);
print "@out\n";
The 'combine' function uses 'eval' to create a clean and efficient transform from the component parts.
The overhead of this 'combine' step is equal to about 10 transform calls, which is insignificant in my application.
##### original posting #####
I need an efficient way to process a sequence of transforms. For example, here are some individual transforms as code references:
# some code references
$f1 = sub {map {$_ + 1} @_};
$f2 = sub {map {log($_)} @_};
$f3 = sub {map {$_ * 3} @_};
They may be combined into a sequence
# combined transform
sub trans1 {&$f3(&$f2(&$f1))};
# some data
@data = (1, 2, 3);
# call the transform
@trans = trans1(@data);
print "@trans\n";
The sequence could have fewer or more steps, so I would like to make an array of code references:
# make a sequence array
@seq = ($f1, $f2, $f3);
# combined transform
sub trans2 {
# for each code reference
for (@seq) {
# transform data
@_ = &$_;
}
# return
return(@_);
}
# call the transform
@trans = trans2(@data);
print "@trans\n";
This works okay, but I wonder if there is a better and faster way.
-
Are you posting in the right place? Check out Where do I post X? to know for sure.
-
Posts may use any of the Perl Monks Approved HTML tags. Currently these include the following:
<code> <a> <b> <big>
<blockquote> <br /> <dd>
<dl> <dt> <em> <font>
<h1> <h2> <h3> <h4>
<h5> <h6> <hr /> <i>
<li> <nbsp> <ol> <p>
<small> <strike> <strong>
<sub> <sup> <table>
<td> <th> <tr> <tt>
<u> <ul>
-
Snippets of code should be wrapped in
<code> tags not
<pre> tags. In fact, <pre>
tags should generally be avoided. If they must
be used, extreme care should be
taken to ensure that their contents do not
have long lines (<70 chars), in order to prevent
horizontal scrolling (and possible janitor
intervention).
-
Want more info? How to link
or How to display code and escape characters
are good places to start.