 The stupid question is the question not asked PerlMonks

### Conversions of SI Units

by choroba (Archbishop)
 on Feb 16, 2019 at 21:57 UTC ( #1230003=CUFP: print w/replies, xml ) Need Help??

My son (11) has just learned SI units and their prefixes at school. They started just with metres and litres, only some of the prefixes (mili, centi, deci, hecto, kilo) and they don't know the floating point yet. Because of his broken arm, he missed several days at school and needed to practice. So, I've written a Tk application for him to practice. It takes one parameter, the number of formulas to generate.

Feel free to localize it using the constants at the beginning. Adding the floating point left as an exercise for the reader.

```#!/usr/bin/perl
use warnings;
use strict;
use feature qw{ say };

use List::Util qw{ shuffle };
use Function::Parameters;
use Tk;

use constant {
SEPARATOR => ',',
OK        => 'OK',
TITLE     => 'SI Units Conversions',
DONE      => 'Done',
QUIT      => 'Quit',
ERRORS    => 'Errors',
};

push @ARGV, -font => 'sans 15';

fun prefixes (@prefixes) {
+{ map +(\$_ => undef), "", @prefixes }
}

fun do_format (\$x) {
my \$f = reverse \$x;
\$f =~ s/(...)(?=.)/\$1\${\SEPARATOR}/g;
return reverse \$f
}

fun validate (\$new_value, @) {
\$new_value =~ /^[0-9\${\SEPARATOR}]*\$/
}

my %known = (l => prefixes(qw( m c d h )),
m => prefixes(qw( m c d k )));

my %times = (m  => 0.001,
c  => 0.01,
d  => 0.1,
"" => 1,
h  => 100,
k  => 1000);

my @exercises;
for (1 .. shift) {
my \$unit = (keys %known)[rand keys %known];
my @prefixes = sort { \$times{\$a} <=> \$times{\$b} }
(shuffle(keys %{ \$known{\$unit} }))[0, 1];
push @exercises, [ \$unit, @prefixes, 1 + int rand 100 ];
\$exercises[-1][-1] *= 10 for 1 .. rand 2;
if (int rand 2) {
my \$times = \$times{ \$prefixes } / \$times{ \$prefixes };
\$exercises[-1]
= [ \$unit, @prefixes[1, 0], \$exercises[-1][-1] * \$times ];
}
}

my (@solutions, @entries);
my \$errors = 0;

my \$mw = 'MainWindow'->new(title => TITLE);
for my \$i (0 .. \$#exercises) {
my \$exercise = \$exercises[\$i];
my \$f = \$mw->Frame->pack;
my \$ratio = \$times{ \$exercise-> } / \$times{ \$exercise-> };
\$f->Label(-text => do_format(\$exercise-> * \$ratio)
. " \$exercise->\$exercise-> = ")
->pack(-side => 'left');
push @entries, \$f->Entry(-textvariable    => \\$solutions[\$i],
-validate        => 'all',
-validatecommand => \&validate,
)->pack(-side => 'left');
\$f->Label(-text => " \$exercise->\$exercise->")
->pack(-side => 'left');
}

my \$f = \$mw->Frame->pack;

\$f->Button(-text    => DONE,
-command => fun () {
for my \$i (0 .. \$#solutions) {

my \$value = (\$solutions[\$i] // "") =~ s/\${\SEPARATO
+R}//gr;
if ((\$value || 0) == \$exercises[\$i]) {
+,
-validate => 'none');
\$solutions[\$i] = OK;
} else {
++\$errors;
}
}
})->pack(-side => 'left');
\$f->Button(-text    => QUIT,
-command => [\$mw => 'destroy'])->pack(-side => 'left');

MainLoop();
say ERRORS, ": \$errors";

It's been a practice for me, too, because of Function::Parameters.

map{substr\$_->,\$_->||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]

Replies are listed 'Best First'.
Re: Conversions of SI Units
by 1nickt (Abbot) on Feb 17, 2019 at 00:45 UTC

Hi choroba, what was it that made you choose Function::Parameters? We have been using Method::Signatures at \$work for several years, but it's very good and stable and the author is always responsive. Wondering what it lacked that you found in F::P. Just wanting to avoid Devel::Declare?

The way forward always starts with a minimal test.
Function::Parameters seem much lighter and faster than Method::Signatures. Also, the fact they integrate nicely with Type::Tiny that we use with Moo makes their adoption easier.

map{substr\$_->,\$_->||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]

Create A New User
Node Status?
node history
Node Type: CUFP [id://1230003]
Front-paged by Discipulus
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others wandering the Monastery: (8)
As of 2020-05-26 18:27 GMT
Sections?
Information?
Find Nodes?
Leftovers?
Voting Booth?
If programming languages were movie genres, Perl would be:

Results (150 votes). Check out past polls.

Notices?