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

I am learning Perl using the Llama book. The code for one of the exercises that I wrote looks completely diffrent than the answer in the book. They use a long if - elseif structure. I was wondering ig anyone could tell me if what I wrote is bad and if so then why? I wrote the following for the Chapter 10 exercise (high-low number guess game).
#!/usr/bin/perl #Guess a number between 1 and 100 game $secret_number = int(1 + rand 100); # print "secret number = $secret_number\n"; # for debugging purposes print "_-_-_-The number guess game-_-_-_\n"; until ($guess eq $secret_number) { if (defined $guess) { my $answer = ($guess < $secret_number) ? "less than" : ($guess > $secret_number) ? "greater than" : ""; print "\nThe number you entered is $answer the secret number.\n"; } print "\nEnter a number between 1 and 100 : "; chomp($guess = <STDIN>); if ($guess =~ /quit|exit|^\s*$/i) { $quit = "yes"; last } } if ($quit =~ /^(yes)/) { print "\nToo bad... you gave up.\n" } else { print "\nYay! You guessed the number correctly!\n"; }

Replies are listed 'Best First'.
Re: Bad Code?
by Abigail-II (Bishop) on Aug 19, 2003 at 14:51 UTC
    Well, you are testing in each iteration whether $guess is defined. But that's not necessary. You know that $guess is undefined the first time around, and then never again.

    Also, people have suggested that you turn on warnings, but they fail to mention that you should do some checking of $guess (to see whether it's a number) before comparing it to $secret_number - otherwise, you will get warnings.

    #!/usr/bin/perl use strict; use warnings; my $secret = 1 + int rand 100; while (print "Your guess > ") { local $_ = <>; chomp; if (!/\S/ || /quit/i || /exit/i) { print "Too bad, you gave up.\n"; exit; } if (/\D/) { print "You didn't enter a non-negative integer\n"; next; } if ($_ == $secret) { print "You guessed the number correctly.\n"; exit; } my $answer = $_ < $secret ? "less" : "greater"; print "The number you entered is $answer than the secret number\n" +; } __END__

    That's how I would do it.

    Abigail

      That is very, very nice.
Re: Bad Code?
by bear0053 (Hermit) on Aug 19, 2003 at 14:19 UTC
    This looks good it works correctly. My only suggestion would be to get use to using strict. becuase when you start writing longer and more complicated programs they are easier to maintain and trouble shoot when you use strict since everything is localized
Re: Bad Code?
by halley (Prior) on Aug 19, 2003 at 14:23 UTC
    There are a lot of ways to do anything in Perl, and your code doesn't loudly scream NO! The proof is in the pudding: does it work? The Llama will probably focus on solutions using methods taught in that chapter, and solutions that are very readable to newcomers to the language.

    It's not to say your code is perfect, and there are a number of minor nits and points of style I'd probably give. However, rather than overload you with suggestions that have historical and/or religious subtleties, I'll skip all that.

    --
    [ e d @ h a l l e y . c c ]

Re: Bad Code?
by Foggy Bottoms (Monk) on Aug 19, 2003 at 14:36 UTC
    I read your code and it seems fine, not that I'd be able to discern between appallingly awful code and tremendously great code...

    There are however a couple changes I'd make : first off, I'd use the pragma use strict; at the very beginning of your code - it then forces you to declare your variables the following way : my $a; or my $a = 17;...
    It prevents you from mixing up eponymous variables specially when you go into loops.

    Second of all, before even testing the number, I'd initialize ask for it... :
    my $guess = 0; # can't be the right one then until($guess == $secret_number) { $guess = <STDIN>; # do the rest }
    Hence the if (defined $guess is useless and you can directly write :
    my $answer = ($guess>$secret_number?("bigger than"):($guess<$secret_number?("smaller than"):""))
    I note that you've used eq : this is a string comparison tool. It's best you use == (as in C). On second thoughts, I've noticed you're using eq because of $guess = <STDIN> in which case you're right eq is better...

    Lastly, instead of using $quit as a string which then makes you use regexes, you'd be better off using a byte : $quit = 1; or even a constant : $quit = YES provided you previouslt declared YES : use constant YES => 1...

    Hope this helps...
Re: Bad Code?
by tcf22 (Priest) on Aug 19, 2003 at 14:20 UTC
    Your code looks fine to me. Remember that in Perl, there is more than one way to do it (TIMTOWTDI).

    Update: I agree with bear0053, that you should use strict, and use warnings is also a good idea.
Re: Bad Code?
by TomDLux (Vicar) on Aug 19, 2003 at 17:50 UTC

    Like Abigail and others say, there are ways to improve your code. But as far as being different from Randall's textbook codee, there's nothing wrong. After all, your code works correctly, right?

    Bonus points for using unless. People are often intimidated by unless or just don't see the opportunity to use it appropriately.

    When you finish a chunk of code, it's worth looking at it to see to see what is clumsy, what can be simplified. In this case, for example, you order the contents of the loop so that detecting 'quit' and exiting the loop happens at the bottom ... because you started with until ($guess eq $secret_number ) { . If the user plays to completion, the exit happens at the top, but if they give it, the loop is exited due to last. Neither is better or more natural than the other, so it's worth considering rotating the loop to natural order: prompt, input, test input, test input, output message.

    until ($guess eq $secret_number) { print "\nEnter a number between 1 and 100 : "; chomp($guess = <STDIN>); if ($guess =~ /quit|exit|^\s*$/i) { $quit = "yes"; last } my $answer = ($guess < $secret_number) ? "less than" : ($guess > $secret_number) ? "greater than": ""; print "\nThe number you entered is $answer the secret number.\n"; }

    Yes, you exit in the middle of the loop, nothing wrong with that. In some languages exiting a loop is tricky, but it's easy in Perl. You were already using last, anyway.

    The next complicated structure is the regex and exit. Look at the artificial variable, $quit. Instead of using the variable, you could move the printed message into the regex condition.

    Hmm .... it's beginning to look like Abigail's solution.

    Your code works. Once you have code that works, Then you can make it work better, do more, more effectively communicate what you consider important.

    --
    TTTATCGGTCGTTATATAGATGTTTGCA

Re: Bad Code?
by Hayl_ (Acolyte) on Aug 19, 2003 at 14:46 UTC
    thanks everyone, i feel better now. i was really concerned when my answer looked totally different than theirs :)
Re: Bad Code?
by Jasper (Chaplain) on Aug 19, 2003 at 15:12 UTC
    Nobody likes a smart arse.

    :) - I'm just jealous 'coz I wasn't writing nested ternaries when I was learning from the llama.

    Jasper