Perl 6有无限的整数(Int)吗?

10

我有一个任务,需要找到与目标字符串最接近的字符串(即编辑距离),但不要同时生成它们。我想使用高水位线技术(也可以说是低水位线技术),同时将最近的编辑距离初始化为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,因此我不能这样做:

在对$closest-so-far赋值时类型检查失败;期望Int但得到了Num (Inf)

我可以将约束改为Num并强制转换为它:

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

然而,这似乎非常不自然。由于NumInt没有关联,我无法像Int(Num)那样设置约束条件。实际上,我只关心第一个值。将其设置为足够大的某些值(例如最长字符串的长度)很容易,但我想要更纯粹的东西。

我是否漏掉了什么?我认为任何具有数字属性的东西都可以有一个特殊的值,比所有其他值都大(或小)。多态之类的。


Real是由IntNum两个角色扮演的,您对此有何看法? - Christoph
但是Real不是Int,而我想把它放入一个只应该是整数的东西中。 - brian d foy
1个回答

10

{希望新的介绍比原来那个更有帮助和准确}

@CarlMäsak在他在这个答案下面写的评论中提到我的第一个版本:

上次我在2014年与Larry谈论这个问题时, 他的理由似乎是... Inf应该适用于Int、Num和Str

(我的第一个答案以一种“回忆”的方式开始,我已经得出结论,这至少是没有帮助的,可能是完全错误的记忆。)

在回复Carl的评论时,我在#perl6-dev in 2016找到了一个相关的宝石,当时Larry写道:

然后我们的政策可以是,如果你想要支持±Inf和NaN的Int,请使用Rat

换句话说,不要让Rat与Int一致,而是让它与Num一致

Larry在6.c中写了这篇文章。我不记得有任何类似的讨论针对6.d

{现在回到我的第一个答案的其余部分}


Num在P6中实现了IEEE 754浮点数类型。根据IEEE规范,此类型必须支持用于表示抽象概念的几个具体值,包括正无穷大的概念。 P6将相应的具体值绑定到术语Inf

鉴于表示无限大的这种具体值已经存在,它成为了一种语言范围内的通用具体值,用于不涉及浮点数的情况,例如在字符串和列表函数中传达无穷大。


我提出的解决方案是使用subset通过where子句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是否支持依赖类型?,看起来粗略的共识是不支持


虽然这可能是Larry的理由,但无限大是一个抽象的概念,因此它并不完全是一个数字。但是,类型的交汇似乎非常有趣。 - brian d foy
1
上次我和Larry谈到这个问题时,他的理由似乎是Inf应该适用于Int、Num和Str,如何实现这一点是次要的。@raiph,你有没有一个链接来支持比这更新的立场? - Carl Mäsak
brian-d-foy @CarlMäsak 我已经四处搜寻并思考了Carl提供的链接和其他一些我找到的信息。虽然我没有直接问过Larry,但现在我怀疑自己对他的理由的记忆是错误的。我已经相应地编辑了我的答案。 - raiph

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接