gpt4 book ai didi

raku - 来自非类型化数组的类型化数组

转载 作者:行者123 更新时间:2023-12-05 01:28:12 24 4
gpt4 key购买 nike

假设我们有以下 multi sub :

multi sub abc(Int        @array) { say 10, ' ', @array; }

multi sub abc(Array[Int] @array) { say 20, ' ', @array; }

multi sub abc(Str @array) { say 30, ' ', @array; }

multi sub abc(Array[Str] @array) { say 40, ' ', @array; }

this question 中所述,使用类型化数组调用它们可能会变得冗长:
abc Array[Int].new([1,2,3]);

abc Array[Array[Int]].new([Array[Int].new([1,2,3]), Array[Int].new([2,3,4])]);

如果可以从文字中推断出类型,这样我们就可以做这样的事情,那就太好了:
abc typed([1,2,3]);

abc typed([[1,2,3],[2,3,4]]);

abc typed(['a', 'b', 'c']);

abc typed([['a', 'b', 'c'], ['b', 'c', 'd']]);

更进一步,让我们添加一个为我们进行类型推断的子句:
multi sub abc(@array) { abc typed(@array); }

现在我们可以在没有额外强加语法的情况下获得完整的推理:
abc [1,2,3];

abc [[1,2,3],[2,3,4]];

abc ['a', 'b', 'c'];

abc [['a', 'b', 'c'], ['b', 'c', 'd']];

以上显示如下:
10 [1 2 3]
20 [[1 2 3] [2 3 4]]
30 [a b c]
40 [[a b c] [b c d]]

以下是 typed 的简单版本适用于:
  • Array[Int]
  • Array[Array[Int]]
  • Array[Str]
  • Array[Array[Str]]

  • 我的问题是,您将如何实现这种类型推断?有没有更好的方法?是否已经有类似的设施可用?
    sub type-of(\obj)
    {
    if obj.^name eq 'Array'
    {
    if obj.map({ type-of($_).^name }).all eq obj.map({ type-of($_).^name })[0]
    {
    my $type = type-of(obj[0]);
    return Array[$type];
    }
    return Array;
    }

    if obj.^name eq 'Int' { return Int; }
    if obj.^name eq 'Str' { return Str; }
    }

    sub typed(\obj)
    {
    if obj.^name eq 'Array'
    {
    return type-of(obj)(obj.List.map({ $_.&typed }).Array);
    }

    return (type-of(obj))(obj);
    }

    最佳答案

    calling these with typed arrays can get verbose



    也许您对所有内容都进行了类型约束,这有点过头了?

    您还可以将类型存储在常量中,稍微缩短代码:
    my constant AI = Array[Int];
    dd AI.new([1,2,3]);
    dd Array[AI].new([AI.new([1,2,3]), AI.new([2,3,4])]);

    My question is, how would you go about implementing this sort of type inference?



    .WHAT pseudo-method返回调用者的类型对象。所以你可以使用它来获取事物的类型,你可以使用 =:= container identity operator确定您是否正在处理 Array . (或者,您可以使用 ~~ smartmatch 代替,这样也可以捕获 Array 的子类)。

    这是使用自定义环绕运算符的此类使用的示例实现:
    sub circumfix:<♥[ ]> (|c) {
    my \array = circumfix:<[ ]>(|c);
    return array unless try array.elems;

    (my $type := array.head.WHAT) =:= Array
    and $type := (array[0] = circumfix:<♥[ ]>(array.head<>)).WHAT;

    my $type-it := True;
    for array.tail: *-1 {
    (my $el-type := .WHAT) =:= Array
    and $el-type := ($_ = circumfix:<♥[ ]>(.<>)).WHAT;
    next if $el-type =:= $type;
    $type-it := False;
    }
    $type-it ?? Array[$type].new: array !! array
    }

    dd ♥[<1 2 3>];
    dd ♥[<a b c>];
    dd ♥[[1e0,2], [2,3], [3,3]];
    dd ♥[[1,2], [2,3], [3,3]];
    dd ♥[[[[1],],],];

    # OUTPUT:
    # Array[IntStr].new(IntStr.new(1, "1"), IntStr.new(2, "2"), IntStr.new(3, "3"))
    # Array[Str].new("a", "b", "c")
    # [[1e0, 2], Array[Int].new(2, 3), Array[Int].new(3, 3)]
    # Array[Array[Int]].new(Array[Int].new(1, 2), Array[Int].new(2, 3), Array[Int].new(3, 3))
    # Array[Array[Array[Array[Int]]]].new(Array[Array[Array[Int]]].new(Array[Array[Int]].new(Array[Int].new(1))))

    我们使用 |c to capture the args并简单地将它们交给核心 [ ]将成为常规 Array 的外加符为我们。

    然后,我们 try 看看是否 Array我们得到了任何元素:如果没有,我们将不知道如何对其进行参数化,而且懒惰的东西不会让我们找到 .elems ,因此 try .

    此时,我们知道我们的 Array 中至少有一个元素。 ,所以我们捕获它并使用 .WHAT得到它的类型。然后,我们使用 =:=检查它是否是 Array ,如果是,我们只需对其进行递归,存储结果,更新 $type到返回的类型。 <>位只是到 decont the Array :
        (my $type := array.head.WHAT) =:= Array
    and $type := (array[0] = circumfix:<♥[ ]>(array.head<>)).WHAT;

    接下来,我们有 for环形。我们从第二个元素开始,因为我们在确定要使用的类型时已经处理了第一个元素。

    如果任何其他元素与 $type 的类型不同我们无法参数化我们的 Array ,所以我们简单地循环并检查它们的类型,在 Arrays 上递归做同样的事情。 .如果我们发现任何不同的类型,我们设置一个标志( $type-it ),以指示当前 Array不应该被参数化(我们仍然继续循环,以便我们递归和参数化任何剩余的 Array s)。

    最后,如果设置了标志,我们使用 $type参数化一个新的 Array和;否则我们返回我们的 array照原样。

    简单:)

    P.S.:值得注意的是 Perl 6 支持自引用 Arrays ,并且上面的代码会挂起,比如说,这个设置:
    my @a; @a[0] = @a;
    dd ♥[@a];

    你需要实现一些东西来标记它已经看到的东西; something similar to this (如果您将 NQP 代码转换为纯 Perl 6)

    关于raku - 来自非类型化数组的类型化数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45377826/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com