Управляющий оператор Raku, чтобы числовые строки интерпретировались как числовые - PullRequest
8 голосов
/ 29 октября 2019

У меня есть большой хэш массивов,

%qual<discordant> (~ около 13199 значений, таких как '88 .23', '99 .23 'и т. Д.

, которые находятся в диапазоне 88-100,и считываются из текстовых файлов,

, и когда я печатаю %qual<discordant>.min и %qual<discordant>.max, я вижу, что значения явно неверны.

Я могу это исправить, изменив способ отображения данных. прочитайте текстовые файлы:

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

до

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

но это не было интуитивно понятно, это заняло у меня несколькоминут, чтобы понять, почему Raku / Perl6 поначалу давал явно неверные ответы. Эту ошибку было бы очень легко пропустить. В perl5 стандартным поведением было бы все равно обрабатывать эти строки как числа.

Тамдолжен быть какой-то управляющий оператор, чтобы сделать это поведением по умолчанию, как я могу это сделать?

1 Ответ

10 голосов
/ 30 октября 2019

Проблема / особенность заключается в том, что в Raku, когда вы читаете строки из файла, они становятся строками (или объектами типа Str). Если вы вызовете .min и .max для массива из Str объектов, то семантика строки будет использоваться для определения того, что-то больше или меньше.

Там - это специальные значенияв Раку, которые действуют как ценности в Perl. В раку это называется " алломорф ". Это Str, но также Num, или Rat, или Int, или Complex.

Синтаксис для создания соответствующего алломорфа для строки в $_: << $_ >>. Поэтому, если вы измените строку, которая читает слова, на:

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

, тогда значения в @line будут либо Str, либо IntStr, либо RatStr. Что должно заставить .min и .max работать так, как вы ожидаете.

Однако, если вы уверены, что только 5-й элемент @line будет числовым, то, вероятно, будет более эффективно преобразоватьStr до числа перед передачей в массив. Более коротким синтаксисом для этого будет префикс +:

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

Хотя это может показаться слишком строковым.

ОБНОВЛЕНИЕ: Я забыл, что на самом деле есть подпрограмма с именемval, который принимает Str и создает соответствующий ему алломорф (или возвращает оригинал Str). Таким образом, код для создания @line может быть записан как:

my @line = $line.words>>.&val
...