我有一个任务,我想找到最接近目标的字符串(因此,编辑距离),而不是同时生成它们.我想我会在初始化最近的编辑距离时使用高水位技术(低,我猜),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;
}
Run Code Online (Sandbox Code Playgroud)
但是,Inf
是一个Num所以我不能这样做:
分配到$ nearest-so-far的类型检查失败; 预期Int但得到Num(Inf)
我可以制定约束Num
并强制执行:
state Num $closest-so-far = Inf;
...
$closest-so-far = $string.chars.Num;
Run Code Online (Sandbox Code Playgroud)
然而,这似乎很不自然.并且,既然Num
和Int
不相关,我就不能有像这样的约束Int(Num)
.我只关心这个第一个价值.很容易将其设置为足够高的东西(例如最长字符串的长度),但我想要更纯净的东西.
有什么我想念的吗?我原以为任何数字的东西都可能有一个特殊的值,它比所有其他值更大(或更小).多态性和所有这些.
{新的介绍,希望比无益/误导的原版更好}
@CarlMäsak,在他的第一个版本之后,他在下面写了这个答案:
上次我和Larry讨论了这个问题{2014年},他的理由似乎是...... Inf应该适用于所有的Int,Num和Str
(我的回答的第一个版本开始于一个"回忆",我得出的结论至少是无益的,似乎是完全错误的记忆.)
在我对Carl的评论做出的研究中,我确实在2016年找到了#perl6-dev中的一个相关宝石,当时Larry写道:
那么我们的政策可能是,如果你想要一个支持±Inf和NaN的Int,请改用Rat
换句话说,不要让Rat与Int一致,使其与Num一致
拉里写了这篇文章6.c
.喜欢讨论我不记得看到任何东西了6.d
.
{现在回到我的第一个回答的其余部分}
Num
在P6中实现了IEEE 754浮点数类型.根据IEEE规范,这种类型必须支持几个具体的值,这些值被保留用于抽象概念,包括正无穷大的概念.P6将相应的具体值绑定到该术语Inf
.
鉴于表示无穷大的这个具体值已经存在,它成为语言范围的通用具体值,表示不涉及浮点数的情况的无穷大,例如在字符串和列表函数中传达无穷大.
我在下面提出的问题的解决方案是where
通过a 使用一个子句subset
.
一个where
子句允许指定运行时分配/结合"typechecks".我引用"类型检查",因为它是最强大的检查形式 - 它在计算上是通用的,并且字面上检查实际的运行时值(而不是静态类型的视图,该值可以是什么).这意味着他们更慢和运行时,不编译时间,但它也使他们的方式更强大的(更不用说比较容易的方式来表达),甚至比依赖类型这是一个比较前沿的功能,那些谁是为先进静态类型检查语言倾向于声称只在他们自己的世界1中可用,并且旨在"通过允许非常富有表现力的类型来防止错误"(但是好好弄清楚如何表达它们......;)).
一个子集的声明可以包括一个where
条款.这允许您命名检查并将其用作命名类型约束.
因此,您可以使用这两个功能来获得您想要的内容:
subset Int-or-Inf where Int:D | Inf;
Run Code Online (Sandbox Code Playgroud)
现在只需将其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
Run Code Online (Sandbox Code Playgroud)
1.请参阅Perl 6是否支持依赖类型?并且它似乎粗糙的共识是没有.