Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Hello there.

I got frustrated a little bit with my problem. I feel totally stuck as well so I hope to find some help here...

Here is my problem: I am using Win32::GUI module to create custom log viewer. This is great as finally I can have functionality all available viewers don't: I want to load a huge log file in the main window and then reload it in other window but filtered with regular expression entered in the main window. The new window is created in the following manner:

${"Window".$WindowCount} = new Win32::GUI::Window ( -name => "Window$WindowCount", -title => "RegExp$WindowCount", -pos => [100, 100], -size => [400, 400], -onTerminate => \&Buffer_OnQuit ) or die "new Window"; ${"Window".$WindowCount}->AddTextfield( -name => "RegExp", -pos => [10, 0], -size => [300, 21], -keepselection => 1 , -prompt => [ "RegExp Filter : ", 75] );
$WindowCount is the global counter which increases everytime new window is created. I need to have many windows opened! Each of them has editbox (for regexp text).
For the example above if $WindowCount == 1 I can get the regexp text like this: $var = $Window1->RegExp->Text but I CANNOT GET it like this:
$counter = 1; $var = ${"Window".$counter}->RegExp->Text
nor like this:
$var = ${"Window"."1"}->RegExp->Text
I get an error: "Can't call method "RegExp" on an undefined value..." Can someone explain it to me?

Replies are listed 'Best First'.
Re: win32 perl module usage problem
by roboticus (Chancellor) on Jan 08, 2010 at 13:34 UTC

    What people are objecting to is that your program is creating new variables at will. Your expression:

    ${"Window".$WindowCount} = new Win32::GUI::Window(...);

    creates a variable named $Window0 when $WindowCount contains a value of 0. Conceptually, it seems like a nice way to do things. But as you gain experience, you find that there are just too many ways to make mistakes, and too many possibilities for unintended consequences. Code that uses this trick tends to be a maintenance headache

    As an example, if $counter doesn't have a value, then you're trying to access the RegExp member of variable $Window, which either doesn't exist or doesn't contain a value. Or perhaps you used $counter for another purpose somewhere, and it contains "foo", in which case $Windowfoo similarly doesn't exist or contain a value.

    When you compute your variable names, you can make mistakes which lead to rather surprising behavior in the event that your expression comes up with something annoying like "_", in which case you'd be mangling the $_ variable.

    So people are suggesting that you put your variables in a hash to limit the possible interactions with other variables. People often use a hash to do this, because you can use your computed name as a hash key, like so:

    $Windows{"Window".$counter} = new Win32::GUI::Window(...);

    However, since your counter is simply a number, BrowserUK is suggesting that you use an array instead of a hash. After all, a hash that uses integers as a key is pretty darned similar to an array in useability:

    $Windows[$counter] = new Win32::GUI::Window(...);

    But an array has better performance1 and is pretty easy for new(er) programmers to use/understand. (Hashes are beautiful, but have a couple of behaviors2 that newer programmers often find surprising.)

    ...roboticus

    Notes:

    1 I think...I've never bothered to profile it, so I could easily be wrong. In any event, it would depend on how (and how frequently) you access it, too.

    2 Specifically, (1) when you iterate through the keys of a hash, the order they keys are traversed is arbitrary, having no relation to the order in which you put the keys in the hash; (2) you can't sort a hash--you can access the keys in sorted order, but you have to create a new sorted list of keys to do it--you can't actually change the order of the items in the hash itself. There may be a couple of others, but they don't come to mind at the moment.

Re: win32 perl module usage problem
by Anonymous Monk on Jan 08, 2010 at 11:21 UTC
    Can someone explain it to me?

    You have decided to use symbolic references, and its biting you :) Use a hash instead.

      Use a hash instead.

      Or better yet. Gain some space and speed by using an array!


      Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
      "Science is about questioning the status quo. Questioning authority".
      In the absence of evidence, opinion is indistinguishable from prejudice.
      I am sorry but I do not understand what you write. I am afraid I need an example. I have to refer to $Window1 somehow and I need to be able to do it dynamically.
        my @Windows; $Windows[ 1 ] = new Win32::GUI::Window ( ... my $var = $Windows[ 1 ]->RegExp->Text;

        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.