gnu@perl has asked for the wisdom of the Perl Monks concerning the following question:

I have an array and I wish to use the elements in it as variable names. Basically, I am dynamically creating objects based upon the number of elements in the array. In order to differentiate between the object they obviously have to have unique names. This is where I use the data from the array.

The problem is that I am not sure how to do this, I have tried a number of mehods on my own to no avail.

Here is a little example of what I am doing.

for (@array){ <variable I want to create from $_> = OBJ->new; ... work using variable... }

I would also like to be able to store the newly created variable in another array for use elsewhere.

Any help is appreciated. TIA.

  • Comment on dynamically creating variables named after the contents of an array
  • Download Code

Replies are listed 'Best First'.
Re: dynamically creating variables named after the contents of an array
by perrin (Chancellor) on Sep 06, 2002 at 18:20 UTC
    Why don't you use a hash instead?

    for (@array){ $hash{$_} = OBJ->new; ... work using variable... }
      Thanks, for some reason that didn't even strike me. I'll give it a try. Anyone with any more ideas. I would kind of like to see what people come up with on this.
•Re: dynamically creating variables named after the contents of an array
by merlyn (Sage) on Sep 06, 2002 at 18:30 UTC
    And if you "want" to do that, I don't "want" to ever have to maintain your code, or hire you as a programmer working for me.

    "variable variables" is definitely the wrong way to go in Perl. It can be done (Perl can do nearly anything), but your maintenance programmer will hunt you down and kill you.

    As others have suggested in this thread, a hash of arrayrefs is the way to go.

    Do not pollute metadata (variable names) with user data (values). Ever.

    -- Randal L. Schwartz, Perl hacker

      > but your maintenance programmer will hunt you down
      > and kill you.

      We can do that?!!

      I just had this wonderful vision of being a contestant on a game show (maybe Payback or something like that. Most likely a Fox show) chasing down a few programmers who work for a fortune 500 company that shall go nameless. But... then I realized that probably over at XOOM.it there's somebody cursing me in ways I can't even understand, wishing they could do the same thing to me.

      Look... if you're out there reading this, I'm really, really sorry. It was my first gig and I didn't know what the hell I was doing but still... you got to admit... there are some kewl things about it. No?

      ()-()
       \"/
        `                                                     
      
    A reply falls below the community's threshold of quality. You may see it by logging in.
Re: dynamically creating variables named after the contents of an array
by ignatz (Vicar) on Sep 06, 2002 at 18:39 UTC
Re: dynamically creating variables named after the contents of an array
by dpuu (Chaplain) on Sep 06, 2002 at 18:33 UTC
    I'm pretty sure that you don't want to do the thing that you're asking to do ... but it is possible.

    approach 1: use an eval:

    my %for_later; foreach my $name (@array) { eval <<"HERE"; my \$$name = new OBJ; do_stuff(\$$name); $for_later{$name} = \$$name; HERE }
    approach2: use a global variable:
    my %for_later; foreach my $name (@array) { no strict; ${$name} = new OBJ; do_stuff(${$name}); $for_later{$name} = ${$name}; }
    These should both work, but would be pretty silly for the scenario you describe. There is no benefit from naming a variable at run-time except in very arcane situations. It would be much better to do the simple:
    my %for_later; foreach my $name (@array) { my $obj = new OBJ; do_stuff($obj); $for_later{$name} = $obj; }
    A couple of final notes: you'll noticed that I used $name in my examples, not $_ as you requested. You could use $_; but I don't recommend it. If you do want your objects to be named, you could always pass the name to the ctor:
    my $obj = new OBJ($name)
    Now the object can remember its own name. --Dave

      Thanks for your input, I agree that you should not create dynamic variables. My wording was a little off on that one. What I need is a list of the object references to the new objects for manipulation later in the program. That is the main reason I cannot perform the work in just one loop.

      As was mentioned above, I think storing the object referneces in a hash would be a good idea.

Re: dynamically creating variables named after the contents of an array
by BrowserUk (Patriarch) on Sep 06, 2002 at 18:44 UTC

    I'm not sure you want to do what you are asking for. You could do

    Update: Arien++ for bringing the error in the line below to my attention. I'd like to claim it was deliberate to prevent the unwary from doing this. It wasn't. It's just something I never do. I'm leaving it as-is with the flag.

    my @array = qw( foo bar baz ); for (@array) { eval "$_ = 'value'"; # Error here!!! }

    You now have three vars $foo='value'; $bar='value'; $baz='value';

    but unless you know what these names are when you write your script--in which case why bother doing this at all--you have no convenient way of using these vars?

    I think what your trying to acheive is an associative array or in Perl's terms, a hash. In which case, to set up a hash from the values of an array, use (for example)

    #name your hash my %hash; #autovivify elements with names from the array.. #using undef simply means they will all be undef. # (all but the first one would be anyway, this just keeps things consi +stant). @hash{@array} = undef; # then to use your named array elements # eg. keyboard or web page. Assume we get the string 'foo' my $varName = getVarNameFromSomeWhere(); # then to use it $hash{$name} = 'we just gave $hash{foo} this as its value'; #and to print it print $hash{$varName}, "\n";

    I hope I read your question correctly, and this is useful, if not, post a reply explaining a little (lot) more of what it is you are trying to achieve.


    Well It's better than the Abottoire, but Yorkshire!
Re: dynamically creating variables named after the contents of an array
by zigdon (Deacon) on Sep 06, 2002 at 18:27 UTC
    Well, I'm not sure it's a good idea to do this, and it will break if you're running with "use strict" (as you defenitly should!), but I think you can do it this way:
    for (@array) { $$_ = OBJ->new; ... }
    see perldoc strict.

    -- Dan

      yup, that does break strict. Been there, done that. But thanks though.
Re: dynamically creating variables named after the contents of an array
by Ryszard (Priest) on Sep 07, 2002 at 08:21 UTC
    I think I may have done something similar to what you want here. The basic idea is to create a new instance of an object at runtime, as opposed to compile time.

    My solution uses file::find to go out and search for modules, then create a new instance of them.

    The literal idea is to be able to create new modules to do different tasks, so you can bounce the server, and it will pick up the new modules automatically. Each module has the same method names, so the main object doesnt have to be aware of any extra method names..

    Anyways, back to the main point, the code snippet i settled on puts a new instance of an obects into $self, based on a variable passed to the method.

    I'm not sure why this would be a maintaince nightmare as merlyn suggested, as the code is self explanitory and the "unknown" modules are in a central repository - perhaps i've missed the point somewhere along the way...

      Read all 3 articles in the discussion starting here and you may understand merlyn's comments better.