Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Raku control statement to make numeric strings interpreted as numeric

Tags:

raku

I have a large hash of arrays,

%qual<discordant> (~approx. 13199 values like '88.23', '99.23', etc.

which ranges from 88-100, and are read in from text files,

and when I print %qual<discordant>.min and %qual<discordant>.max I can see the values are clearly wrong.

I can fix this by changing how the data is read in from the text files:

%qual{$type}.push: @line[5]

to

%qual{$type}.push: @line[5].Num

but this wasn't intuitive, this took me a few minutes to figure out why Raku/Perl6 was giving clearly incorrect answers at first. It would have been very easy to miss this error. In perl5, the default behavior would be to treat these strings like numbers anyway.

There should be some control statement to make this the default behavior, how can I do this?

like image 223
con Avatar asked Oct 29 '19 19:10

con


1 Answers

The problem / feature is really that in Raku when you read lines from a file, they become strings (aka objects of type Str). If you call .min and .max on an array of Str objects, then string semantics will be used to determine whether something is bigger or smaller.

There are special values in Raku that act like values in Perl. In Raku these are called "allomorphs". They are Str, but also Num, or Rat, or Int, or Complex.

The syntax for creating an appropriate allomorph for a string in $_ is << $_ >>. So if you change the line that reads the words to:

my @line = $line.words.map: { << $_ >> }

then the values in @line will either be Str, or IntStr or RatStr. Which should make .min and .max work like you expect.

However, if you are sure that only the 5th element of @line is going to be numeric, then it is probably more efficient to convert the Str to a number before pushing to the array. A shorter syntax for that would be to prefix a +:

%qual{$type}.push: +@line[5]

Although you might find that too line-noisy.

UPDATE: I had forgotten that there's actually a sub called val that takes an Str and creates an appropriate allomorph of it (or returns the original Str). So the code for creating @line could be written as:

my @line = $line.words>>.&val
like image 143
Elizabeth Mattijsen Avatar answered Nov 17 '22 03:11

Elizabeth Mattijsen