Есть ли в Perl 6 бесконечный Int?

У меня была задача, где я хотел найти ближайшую строку к цели (так, отредактировать расстояние), не генерируя их все одновременно. Я подумал, что буду использовать технику высшей отметки (я думаю, низко) при инициализации ближайшего расстояния редактирования до Inf так что любое расстояние редактирования ближе:

use Text::Levenshtein;

my @strings = < Amelia Fred Barney Gilligan >;

for @strings {
    put "$_ is closest so far: { longest( 'Camelia', $_ ) }";
    }

sub longest ( Str:D $target, Str:D $string ) {
    state Int $closest-so-far = Inf;
    state Str:D $closest-string = '';

    if distance( $target, $string ) < $closest-so-far {
        $closest-so-far = $string.chars;
        $closest-string = $string;
        return True;
        }

    return False;
    }

Тем не мение, Inf Num, поэтому я не могу этого сделать:

Сбой проверки типа при присваивании $ ближайший-пока; ожидал Int, но получил Num (Inf)

Я мог бы сделать ограничение Num и приведи к этому:

    state Num $closest-so-far = Inf;
    ...
        $closest-so-far = $string.chars.Num;

Однако это кажется довольно неестественным. И с тех пор Num а также Int не связаны, я не могу иметь ограничение, как Int(Num), Я только действительно забочусь об этом для первой ценности. Легко установить его на что-то достаточно высокое (например, длину самой длинной строки), но я хотел что-то более чистое.

Я что-то упускаю? Я бы подумал, что любая числовая вещь может иметь специальное значение, которое больше (или меньше) всех других значений. Полиморфизм и все такое.

1 ответ

Решение

{новое вступление, которое, надеюсь, лучше, чем бесполезное / вводящее в заблуждение оригинальное}

@ CarlMäsak, в комментарии он написал под этим ответом после моей первой версии:

В прошлый раз, когда я говорил с Ларри об этом {в 2014 году}, его обоснование, по-видимому, было следующим: Inf должен работать для всех Int, Num и Str.

(Первая версия моего ответа началась с "воспоминания", которое я пришел к выводу, было, по крайней мере, бесполезным и правдоподобно совершенно ложным воспоминанием.)

В своем исследовании в ответ на комментарий Карла я нашел один связанный камень в #perl6-dev в 2016 году, когда Ларри написал:

тогда наша политика может быть, если вы хотите Int, который поддерживает ±Inf и NaN, используйте вместо Rat

другими словами, не делайте Rat совместимым с Int, сделайте его совместимым с Num

Ларри написал этот пост 6.c, Я не помню, чтобы что-то подобное обсуждалось для 6.d,

{а теперь вернемся к моему первому ответу}


Num в P6 реализован тип числа с плавающей точкой IEEE 754. Согласно спецификации IEEE этот тип должен поддерживать несколько конкретных значений, которые зарезервированы для замены абстрактных концепций, включая концепцию положительной бесконечности. P6 связывает соответствующее конкретное значение с термином Inf,

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


Решение вашей проблемы, которое я предлагаю ниже, заключается в использовании where оговорка через subset,

where Предложение позволяет указать присваивание / привязку во время выполнения "проверки типов". Я цитирую "проверка типов", потому что это самая мощная из возможных проверок - она универсальна в вычислительном отношении и буквально проверяет фактическое значение времени выполнения (а не статически типизированное представление о том, каким может быть это значение). Это означает, что они медленнее и во время выполнения, а не во время компиляции, но это также делает их намного более мощными (не говоря уже о способе более простого выражения), чем даже зависимые типы, которые являются относительно передовой функцией для тех, кто в продвинутом языки со статической проверкой типов, как правило, претендуют на то, что они доступны только в их собственном мире 1 и предназначены для того, чтобы "предотвращать ошибки, допуская чрезвычайно выразительные типы" (но удачи в выяснении, как их выразить...;)).

Объявление подмножества может включать where пункт. Это позволяет назвать проверку и использовать ее как ограничение именованного типа.

Таким образом, вы можете использовать эти две функции, чтобы получить то, что вы хотите:

subset Int-or-Inf where Int:D | Inf;

Теперь просто используйте это subset как тип:

my Int-or-Inf $foo; # ($foo contains `Int-or-Inf` type object) 
$foo = 99999999999; # works
$foo = Inf;         # works
$foo = Int-or-Inf;  # works
$foo = Int;         # typecheck failure
$foo = 'a';         # typecheck failure

1 См. Поддерживает ли Perl 6 зависимые типы? и кажется, что грубого консенсуса нет.

Другие вопросы по тегам