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

From my module:
if(!defined $Max_Questions){ $Max_Questions = $Total_Questions; &_set_Max_Questions($self,$Max_Questions); }elsif($Max_Questions > $Total_Questions){ croak"Number of questions in $FileName exceeded"; }elsif($Max_Questions < 1){ croak"Must have at least one question in the test."; }else{ &_set_Max_Questions($self,$Max_Questions); }
To me, this code appears somewhat awkward and ugly. Any ideas as to how I could make this a little more neater?

TStanley
--------
Never underestimate the power of very stupid people in large groups -- Anonymous

Replies are listed 'Best First'.
Re: Optimization of a piece of code(Is there a better way than this?)
by Corion (Patriarch) on Jul 03, 2002 at 19:34 UTC

    One thing I see with your code is, that _set_Max_Questions() is called from two places. I would rather set $Max_Questions throughout the if blocks and afterwards (if the program is still alive) call _set_Max_Questions(). As an aside, this seems to be object oriented code - why do you use the form &_set_Max_Questions($self,...) instead of $self->_set_Max_Questions(...) ?

    # First, handle the sensible default $Max_Questions = $Total_Questions unless defined $Max_Questions; # Now check for errors if($Max_Questions > $Total_Questions){ croak "Number of questions in $FileName exceeded"; $Max_Questions = $Total_Questions; }elsif($Max_Questions < 1){ croak "Must have at least one question in the test."; $Max_Questions = 1; } # Now we have a valid number of questions &_set_Max_Questions($self,$Max_Questions);
    perl -MHTTP::Daemon -MHTTP::Response -MLWP::Simple -e ' ; # The $d = new HTTP::Daemon and fork and getprint $d->url and exit;#spider ($c = $d->accept())->get_request(); $c->send_response( new #in the HTTP::Response(200,$_,$_,qq(Just another Perl hacker\n))); ' # web
Re: Optimization of a piece of code(Is there a better way than this?)
by dws (Chancellor) on Jul 03, 2002 at 19:35 UTC
    Could you explain how these statements
    $Max_Questions = $Total_Questions; &_set_Max_Questions($self,$Max_Questions);
    differ? The second looks odd. I would expect it to read   $self->_set_Max_Questions($Total_Questions); unless you're depending later on have $Max_Questions defined. Seeing it written as is, I'm left with the suspicion that there's some odd stuff going on elsewhere.

      The _set_Max_Questions function sets a parameter within the object that contains the number of questions that will be asked in the test. The $Total_Questions variable is the total number of questions that are in the question file that was passed when creating the actual object.

      TStanley
      --------
      Never underestimate the power of very stupid people in large groups -- Anonymous
Re: Optimization of a piece of code(Is there a better way than this?)
by FoxtrotUniform (Prior) on Jul 03, 2002 at 19:38 UTC

    How about something like:

    # default $Max_Questions = $Total_Questions unless defined $Max_Questions; # check boundaries croak "Number of questions in $FileName exceeded" if $Max_Questions > $Total_Questions; croak "Must have at least one question in the test" if $Max_Questions < 1; # good to go &_set_Max_Questions($self, $Max_Questions);

    Update: D'oh! Corion beat me to it... but I like croak ... if better than if ... croak in this case; I think it makes it more obvious that the boundary checks are error conditions, rather than correctable "mistakes" (like undefined $Max_Questions).

    Update 2: Fixed syntax error... thanks TStanley.

    --
    The hell with paco, vote for Erudil!
    :wq

Re: Optimization of a piece of code(Is there a better way than this?)
by suaveant (Parson) on Jul 03, 2002 at 19:28 UTC
    Well... most obvious save is...
    if($Max_Questions > $Total_Questions){ croak"Number of questions in $FileName exceeded"; }elsif($Max_Questions < 1){ croak"Must have at least one question in the test."; }else{ &_set_Max_Questions($self,(defined $Max_Questions ? $Max_Questions : + $Total_Questions)); }
    you can also do $self->_set_Max_Questions(...) to make your code look more object oriented :) Update err, the $self-> thing is assuming you are using OO, based on the $self...

    Update This is just plain wrong, see post below.

                    - Ant
                    - Some of my best work - (1 2 3)

      I don't find this obvious at all, as it behaves differently.

      In the original code, if $Max_Questions is undefined, it gets a default value. In your code, if $Max_Questions isn't defined, you'll get two warnings, and it will croak with "Must have at least one question in the test.". The check on definedness of $Max_Question will not be reached if $Max_Question isn't defined.

      I don't think there's much wrong with the original code, and I suggest leaving as it is.

      Abigail

        Ack... good point, my bad... I missed the obvious...

                        - Ant
                        - Some of my best work - (1 2 3)

Re: Optimization of a piece of code(Is there a better way than this?)
by theorbtwo (Prior) on Jul 03, 2002 at 20:47 UTC

    One thing that nobody else has mentioned: the first if clause can be replaced with $Max_Questions ||= $Total_Questions. (Note, though, that this has different behavor then your code when $Max_Questions is defined, but false ("0" or ""). Your code will fall through to $Max_Questions<1, mine will use $Total_Questions instead.)


    We are using here a powerful strategy of synthesis: wishful thinking. -- The Wizard Book

Re: Optimization of a piece of code(Is there a better way than this?)
by TStanley (Canon) on Jul 03, 2002 at 23:00 UTC
    Thanks to all for your suggestions, and I now give you the final code release (the entire subroutine where the snippet is found):
    sub generate{ my $self=shift; my $Total_Questions=_get_FileLength($self); my $FileName=_get_FileName($self); my $Data=shift; my $Max_Questions=shift; $Max_Questions = $Total_Questions unless defined $Max_Questions; croak"Number of questions in $FileName exceeded" if $Max_Questions > $Total_Questions; croak"Must have at least one question in test" if $Max_Questions < 1; &_set_Max_Questions($self,$Max_Questions); # # Original Code # # if(!defined $Max_Questions){ # $Max_Questions=$Total_Questions; # &_set_Max_Questions($self,$Max_Questions); # }elsif($Max_Questions > $Total_Questions){ # croak"Number of questions exceeds the amount in $FileName"; # }elsif($Max_Questions < 1){ # croak"Must have at least one question in the test"; # }else{ # &_set_Max_Questions($self,$Max_Questions); # } my %Randoms=(); my @Randoms=(); my %Test_Questions=(); my %Test_Answers=(); my %Question_Lengths=(); my $E; for(1..$Max_Questions){ my $question_number=int(rand($Total_Questions)+1); redo if exists $Randoms{$question_number}; $Randoms{$question_number}=1; } @Randoms=keys %Randoms; &_shuffle(\@Randoms); for(my $D=0;$D<$Max_Questions;$D++){ $Test_Answers{$Randoms[$D]}=pop @{$$Data{$Randoms[$D]}}; $Test_Questions{$Randoms[$D]} = $$Data{$Randoms[$D]}; } foreach my $key(keys %Test_Questions){ $E=@{$Test_Questions{$key}}; $Question_Lengths{$key}=$E; } return \%Test_Questions,\%Test_Answers,\%Question_Lengths,\@Randoms; }


    TStanley
    --------
    Never underestimate the power of very stupid people in large groups -- Anonymous