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

Fellow monks,
I'm in the middle of a project and I've run into a small problem in trying to keep strict.

I have a bitmask which is related to tests to be run. The easiest way I've determined to do this is, if the bit is set, run the test, but i do this with an object function call from the var. I know otherways around this, but I'm looking for effciency. And I don't know that 16 if statements are better then using "no strict refs;".

Here's what I'm talking about, keep in mind I have to add "no strict refs" to the module code in order for it to work this way.
use strict; my %byte; my $mask = "267"; #example my @tests = ("test0", "test1", "test2", "test3", "test4", "test5", "test6", "test7", "test8"); @byte{@tests}= map { 1<<$_ } 0..8; #props to tye foreach my $test (@tests){ if($mask & $byte{$test}){ $mask = $mask ^ $byte{$test} unless $t->$test(); #if the test returned false we unset the bit } }
So, in your opinion, is there a better way to do this and still keep strict?

Replies are listed 'Best First'.
Re: Function refs, and trying to keep strict
by sauoq (Abbot) on Sep 25, 2003 at 02:33 UTC

    If you don't want to use no strict 'refs'; you'll have to use hard references rather than symbolic references.

    Something like:

    my @tests = \( &T::test0, &T::test1, . . . );
    and in your loop you'd make the call like
    $test->($t); # Sending the $t object as the first arg...

    An alternative might be to use eval()...

    . . . unless eval "\$t->$test()";

    If you go the hard reference route, you can use eval to create closures to wrap your method calls:

    sub create_closure { my $t = shift; my $m = shift; my $r = eval 'sub { $t->' . $m . '() }'; }
    Then you populate another hash with your actual tests by using another map():
    my @execute{@tests} = map { create_closure( $t, $_ ) } @tests;
    and then your loop changes to something like
    foreach my $test (@tests){ if($mask & $byte{$test}){ $mask = $mask ^ $byte{$test} unless &$execute{$test}; #if the test returned false we unset the bit } }

    Which is best depends on what you are actually doing. Where does $t come from? If inheritance is an issue, avoid specifying the package as in my first example. If the tests do something complicated, you might prefer to avoid using eval... if $t is iterating over a list, you might want to avoid creating closures with eval. Etc. Etc.

    P.S. None of this code has been tested.

    -sauoq
    "My two cents aren't worth a dime.";
    
Re: Function refs, and trying to keep strict
by Abigail-II (Bishop) on Sep 25, 2003 at 07:53 UTC
    What's the problem with use "no strict 'refs'"? While the use of strictness is good, code that bends itself backwards just to satisfy strictness isn't something I fancy.

    Remember that Perl, unlike many other languages, is there to serve the programmer, instead of making the programmer a slave of the language. But if you slab 'use strict' on top of your program, without the willingness of turning it off when appropriate, you're programming in a unPerlish fashion.

    Remember, Java is thataway.

    Abigail

      It's actually not so much of a problem to use "no strict refs". However I've found in the past that I'm easily overlooking something that could kill two birds with one stone.
      That is, run smoothly and keep me within the binds of strict. I understand that the ability to remove those features is there for a reason, and i'm not ashamed to use it. But it never hurts to ask.
      I'm also well aware that many of you understand this language far better then i and expose me to new methods, which is a very good thing indeed.

Re: Function refs, and trying to keep strict
by Beechbone (Friar) on Sep 25, 2003 at 08:05 UTC
    foreach my $test (@tests){ if($mask & $byte{$test}){ if (my $method = $t->can($test)) { $mask = $mask ^ $byte{$test} unless $t->$method(); } # else error handling! #if the test returned false we unset the bit } }
    Whenever you have the name of a method and need a coderef, use can(), it will return undef if the object has no such method or a CODE ref otherwise.
Re: Function refs, and trying to keep strict
by graff (Chancellor) on Sep 25, 2003 at 02:29 UTC
    Would there be anything wrong with using eval here? (I honestly don't know -- just guessing -- and of course the following is untested):
    ... for my $test ( @tests ) { if($mask & $byte{$test}) { # (updated: forgot this line initiall +y) eval "\$t->$test() or die"; $mask ^= $byte{$test} if ( $@ ); } } ...
    I may be wrong, but if I understand your post, I would expect something like this to do what you want while keeping "strict".