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

Hey, so I'm fairly new to perl and was experimenting with a random number generator and some other things as a sort of intelligence test, long story short, I didn't make it very far. I'd like to ask the user if they accept the challenge, but also have it loop and ask again for user-input if a non-acceptable answer is entered. Here is the segment of my code where the error "Can't call method "untill" without a package or object reference"

#!usr/bin/perl use strict; use warnings; use diagnostics; my $range = 100; my $random_number = int(rand($range)); my $answer = 0; print "Do you accept this challenge? "; Do { chomp (my $response = <>); if ($response eq 'yes' || 'Yes' || 'YES' || 'y') { $answer = $answer + 1; } elsif ($response eq 'no' || 'No' || 'NO' || 'n') { $answer = $answer + 2; } else { print "Please respond with 'yes' or 'no'\n\n"; } }until $answer > 0;

Replies are listed 'Best First'.
Re: User input check 'Do until' loop
by Eliya (Vicar) on Mar 13, 2012 at 12:25 UTC

    First, Perl in case-sensitive, i.e. Do is not do.

    Then, in your if/elsif conditions, you'd need to repeat the "$response eq" part

    if ($response eq 'yes' || $response eq 'Yes' || $response eq 'YES' + || $response eq 'y') {

    or use a regex match such as

    if ($response =~ /^y(?:es)?$/i) {
      Ahh wow, what a ridiculous fix, alls working fine now, thank you :)
Re: User input check 'Do until' loop
by tobyink (Canon) on Mar 13, 2012 at 13:08 UTC

    As others have pointed out, this won't work:

    if ($response eq 'yes' || 'Yes' || 'YES' || 'y')

    ... and they've pointed out some ways of fixing it. In the spirit of TIMTOWTDI (there's more that one way to do it), I'll suggest the smart match operator, which is available from Perl 5.10.

    if ($response ~~ ['yes', 'Yes', 'YES', 'y'])

    If you factor out the case-sensitivity by forcing $response to lower case, then it starts looking a little nicer:

    if (lc $response ~~ ['yes', 'y'])

    If you factor out the case-sensitivity by forcing $response to lower case, then it starts looking a little nicer:

    if (lc $response ~~ ['yes', 'y'])

    And some people would probably prefer the qw() operator (which builds an array by splitting a string on whitespace):

    if (lc $response ~~ [qw(yes y)])
    perl -E'sub Monkey::do{say$_,for@_,do{($monkey=[caller(0)]->[3])=~s{::}{ }and$monkey}}"Monkey say"->Monkey::do'
Re: User input check 'Do until' loop
by Anonymous Monk on Mar 13, 2012 at 12:29 UTC
    #!usr/bin/perl

    You mean #!/usr/bin/perl

    Do  {

    You mean do {

    if ($response eq 'yes' || 'Yes' || 'YES' || 'y') { $answer = $answer + 1;

    The or operators just don't work that way. You should write lc $response eq 'yes' or lc $response eq 'y' instead.

    Furthermore, I don't see why you are incrementing $answer when you could just say $answer = 1

Re: User input check 'Do until' loop
by Anonymous Monk on Mar 13, 2012 at 21:43 UTC
    I realize you wanted to understand how to implement this yourself, and I'm glad others have already offered you good answers.

    However a big part of programming in Perl is the virtue of Laziness...and knowing when (and how) to let others do the work for you.

    The CPAN has a number of modules that can handle this kind of interactive prompt-read-validate process for you. For example, here is your entire input validation code rewritten using the IO::Prompter module:

    use IO::Prompter; my $answer = prompt("Do you accept this challenge? ", -yesno) ? 1 : 2;

    Whenever you're faced with what feels like a simple and commonly needed task, its always a good idea to see whether (a) Perl already has it built-in or (b) someone got fed-up and added it already.