Note that there are some explanatory texts on larger screens.

plurals
  1. POCreating subs on the fly from eval-ed string in perl
    primarykey
    data
    text
    <p>I need to transform data structures from a list of arrays into a tree-like one. I know the depth of the tree before I start processing the data, but I want to keep things flexible so I can re-use the code.</p> <p>So I landed upon the idea of generating a subref on the fly (from within a Moose-based module) to go from array to tree. Like this (in a simplified way):</p> <pre><code>use Data::Dump qw/dump/; sub create_tree_builder { my $depth = shift; return eval join '', 'sub { $_[0]-&gt;{$_[', join(']}-&gt;{$_[', (1..$depth)), ']} = $_[', $depth + 1 , '] }'; } my $s = create_tree_builder(5); my $tree = {}; $s-&gt;($tree, qw/one two three four five/, 'a value'); print dump $tree; # prints # { # one =&gt; { two =&gt; { three =&gt; { four =&gt; { five =&gt; "a value" } } } }, # } </code></pre> <p>This opened up worlds to me, and I'm finding cool uses for this process of eval-in a parametrically generated string into a function all over the place (clearly, a solution in search of problems).</p> <p>However, it feels a little too good to be true, almost.</p> <p>Any advice <em>against</em> this practice? Or suggestion for improvements?</p> <p>I can see clearly that eval-ing arbitrary input might not be the safest thing, but what else?</p> <h1>Follow up</h1> <p>Thanks for all the answers. I used amon's code and benchmarked a bit, like this: </p> <pre><code>use Benchmark qw(:all) ; $\ = "\n"; sub create_tree_builder { my $depth = shift; return eval join '', 'sub { $_[0]-&gt;{$_[', join(']}-&gt;{$_[', (1..$depth)), ']} = $_[', $depth + 1 , '] }'; } my $s = create_tree_builder(5); $t = sub { $_[0] //= {}; my ($tree, @keys) = @_; my $value = pop @keys; $tree = $tree-&gt;{shift @keys} //= {} while @keys &gt; 1; $tree-&gt;{$keys[0]} = $value; }; cmpthese(900000, { 'eval' =&gt; sub { $s-&gt;($tree, qw/one two three four five/, 'a value') }, 'build' =&gt; sub { $t-&gt;($tree, qw/one two three four five/, 'a value') }, }); </code></pre> <p>The results are clearly in favour of building the tree, not of the eval'ed factory:</p> <pre><code> Rate build eval build 326087/s -- -79% eval 1525424/s 368% -- </code></pre> <p>I'll admit I could have done that before. I'll try with more random trees (rather than assigning the same element over and over) but I see no reason that the results should be different. </p> <p>Thanks a lot for the help.</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.
 

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