Beefy Boxes and Bandwidth Generously Provided by pair Networks
XP is just a number

Comment on

( #3333=superdoc: print w/replies, xml ) Need Help??

IO::Prompt::Hooked handles the details of prompting, detecting an interactive environment, and accepting callbacks to validate user input and to issue meaningful warnings if the user input is invalid. It continues to loop upon invalid input until it gets good input, or until an optional "tries" count reaches zero. Here's an example of how it could be used for your project.

use strict; use warnings; use Scalar::Util qw( looks_like_number ); use IO::Prompt::Hooked; my %rates = ( 'pounds' => 1, 'usd' => 1.6, 'marks' => 3.0, 'french francs' => 10.0, 'yen' => 174.8, 'swiss francs' => 2.43, 'drachma' => 492.3, 'euro' => 1.5 ); my ($from, $to) = get_targets(\%rates); my $value = get_value(); my $converted = $value * ($rates{$to} / $rates{$from}); printf "$value $from is %.2f $to.\n", $converted; # Manage prompting for "from" and "to" currencies. sub get_targets { my $currencies = shift; return map { get_currency($_, $currencies) } ('Enter your starting currency:', 'Enter your target currency:'); } # Prompt for an individual currency. 5 tries. Die if we don't get # good input. sub get_currency { my ($msg, $curr) = @_; my $in = prompt( message => $msg, tries => 5, validate => sub { return exists $curr->{lc shift}; }, error => sub { my $valid = join ', ', keys %{$curr}; return "Currency must be one of the following: ($valid).\n" . "$_[1] tries remaining.\n"; }, ); die 'Too many tries. Consult someone who can read.' unless defined $ +in; return lc $in; } # Prompt for a value to convert. Die if we don't get good input after # five tries. sub get_value { my $input = prompt( message => "Enter an amount to convert:", default => 0, tries => 5, validate => sub { return looks_like_number shift; }, error => sub { return "Amount must be a number. $_[1] tries remaining.\n"; }, ); die "Unable to obtain a valid value for conversion." unless defined +$input; return $input; }

Here we prompt for a "from" and a "to" currency. We provide the user five tries at getting it right, and upon receiving invalid input, we prompt with additional information enumerating the valid inputs. If after five tries the user can't figure out how to get it right, we die. Then we move on to getting a value, and again loop until we actually get a number (or until the allotted number of tries expires). Finally, we perform the conversion, and output it, rounded to two decimal places.

This is sort of a shameless plug for the module. What I like is that it handles the logic and looping. All the module's user has to do is provide callback subs that perform the validation, and that provide an error string in case of bad input. The error string could also be a simple string instead of a subref, but the subref provides the opportunity to output the number of remaining tries. The module is based on IO::Prompt::Tiny, but while it's still smaller and easier to use than the granddaddy, "IO::Prompt", it's not tiny either. ;)

As for how this example code turned out: You might say, "But it's bigger than the original code." ...Yes, it is. But it is doing more; it's validating both the targets and the numeric values, it's providing meaningful messages for invalid input, and it's dieing if the user can't seem to figure out how to provide valid input after a reasonable number of tries.

Update: Changed all hash keys to lower case per frozenwithjoy's observation. Output will be 'usd' instead of 'USD'. Does it matter? ;)


In reply to Re: a hash and 2 loops--not working by davido
in thread a hash and 2 loops--not working by jhumphreys

Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post; it's "PerlMonks-approved HTML":

  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.
  • Log In?

    What's my password?
    Create A New User
    and all is quiet...

    How do I use this? | Other CB clients
    Other Users?
    Others chanting in the Monastery: (8)
    As of 2018-03-20 12:29 GMT
    Find Nodes?
      Voting Booth?
      When I think of a mole I think of:

      Results (251 votes). Check out past polls.