Beefy Boxes and Bandwidth Generously Provided by pair Networks
Don't ask to ask, just ask

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
    [choroba]: LanX I miss working in a bank sometimes...
    [Corion]: Discipulus: Ooof. Especially yearly things are things I like to automate instead of trying to remember how I did things last year...
    [Corion]: And the second rule that I've learned is, that there is no one-off job, so writing a program for it pays off almost immediately. The third rule is to give all my programs numbers and have them reproduce that number in the name of their output files. :)
    [Discipulus]: the true part is that also specification change between years.. but well our job is cheap but dont abuse of us.. ;=)
    [LanX]: Choroba: do you miss chaos with ties? apply at the US government.. ;)
    [ambrus]: Corion: those are good rules.
    [ambrus]: Discipulus: oh sure. the input data has different filenames every time I get them.
    [ambrus]: the directory structure may be 1, 2, or 3 deep, it may have spaces in the filename or not, it has dates in various format, different keywords for the same meanings, and the dates and other keywords are assembled in various ways.

    How do I use this? | Other CB clients
    Other Users?
    Others meditating upon the Monastery: (14)
    As of 2017-03-29 12:12 GMT
    Find Nodes?
      Voting Booth?
      Should Pluto Get Its Planethood Back?

      Results (350 votes). Check out past polls.