Есть ли в 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 зависимые типы? и кажется, что грубого консенсуса нет.