in reply to Re: Building Multi-Level Hash dynamically
in thread Building Multi-Level Hash dynamically

The key is to use eval in string form.

It really almost never is. String eval is great if you want to generate code from something that looks like code it's a lot less great if you want to generate data structures. Your code is pretty susceptible to errors if @array happens to contain certain characters. Also, it's extremely inefficient to use the compiler for this kind of thing.

  • Comment on Re^2: Building Multi-Level Hash dynamically

Replies are listed 'Best First'.
Re^3: Building Multi-Level Hash dynamically
by Firefly258 (Beadle) on Dec 05, 2006 at 18:31 UTC
    What would be your method of choice to solve OP's problem?

    My code is susceptible to a lot of errors, I'm aware, I hope it never gets used "as is" in production code. :) As for the types of characters in the array that could cause mayhem, could you point me in the direction of them? I'd very much appreciate that.

    Also, it's extremely inefficient to use the compiler for this kind of thing

    If i'm not mistaken and understand it right, the contents to a string form of eval are not known at compile time, and when the interpreter does get around to compiling and evaling the string, it is executed in the same way statically typed code (if that's the right term) is. So I'm not sure I understand what you mean. Can you please clarify?

    I'm aware of the dangerous implications of eval"" but I also have an inclination to think that evaling code for constructing other code/data structures might be more effecient than running through various loops and conditional constructs and assigning to references to get a structure constructed. It definitely is faster. Sriram Srinivasan has a section in advprog that deals with Using Eval for Efficiency to construct faster regular expressions amongst other useful things.



    perl -e '$,=$",$_=(split/\W/,$^X)[y[eval]]]+--$_],print+just,another,split,hack'er
      As for the types of characters in the array that could cause mayhem, could you point me in the direction of them? I'd very much appreciate that.
      How about this:
      my @array = ('system("rm qq(/tmp/*)")', '};die#');
      This is only slightly serious, but it does show the complications you'll get into if you can't trust your input. You could probably prevent a lot of nastiness by making sure every value is correctly quoted, but that would also make the whole thing less efficient.
      I'm aware of the dangerous implications of eval"" but I also have an inclination to think that evaling code for constructing other code/data structures might be more effecient than running through various loops and conditional constructs and assigning to references to get a structure constructed.
      That's true, but you'd better be sure that the data is in exactly the right format or you can end up with all kinds of bugs. I'm not sure that the perl parser is actually faster than a good "custom parser" if you have a relatively stable data structure.

      Sriram Srinivasan has a section in advprog that deals with Using Eval for Efficiency to construct faster regular expressions amongst other useful things
      Yeah, but regexes aren't data, they're code. The advantage of compiling code on the fly is that you can then reuse the compiled code. That's when you get the real speedups. Even though the perl parser is pretty fast, if you're generating data, that means you'll have to run all the data through the compiler.

      Oops, forgot one:
      What would be your method of choice to solve OP's problem?
      If I wanted a silly structure like that, I'd probably do it like this:
      #!/usr/bin/perl use strict; use warnings; use Data::Dumper; my @arr = qw(aa bb cc dd ee ff); sub build { my %hash; my $ref = \%hash; while (defined (my $element = shift @_)) { $ref = ($ref->{$element} = @_ ? {} : 0); } \%hash; } print Dumper build(@arr);
      That should be fast enough for almost all purposes (about 10 5 times faster than the eval string method), and it has none of the security problems.

      Benchmark for the interested:

      Updated benchmark, fixed bug.