metaprogramming - 使用捕获的类型来键入类的属性

标签 metaprogramming raku parametric-polymorphism

我已经按照 SO 问题的答案中的说明进行操作
How can classes be made parametric in Perl 6? .但是,我遇到了一些软障碍。我正在尝试使用类型捕获键入内部类的属性并收到以下错误:

Died with X::TypeCheck::Assignment
  in submethod BUILDALL at ...
  in method insert at ...
  in block <unit> at ...

在下面的例子中,我输入了类 BinaryNode$.item属性(带有 T )但这样做会导致上述错误:
class BinarySearchTree {
    my role BTSImpl[::T] {
        my class BinaryNode is rw {
            has T $.item; 
            has BinaryNode $.left;
            has BinaryNode $.right;
        }

        method create-node( T $x ) {
            BinaryNode.new(item => $x)
        }
    }

    method ^parameterize(Mu:U \this, Mu \T) {
        my $type := this.^mixin: BTSImpl[T];
        $type.^set_name: this.^name ~ '[' ~ T.^name ~ ']';
        $type
    }
}

my $bst = BinarySearchTree[Int].new;
$bst.create-node(6);

最佳答案

首先,几乎不需要执行 class + ^parameterize + role诡计。它出现在一些内部结构中,因为它有助于处理一些引导问题(根据自身定义语言时那种乐趣)。但是,在正常的 Raku 代码中,只需编写一个参数 role而不是 class .从消费者的角度来看,通常没有区别;一 jar :

  • 调用 .new在它上面创建一个实例(它实际上创建了一个类,称为“双关语”,在幕后制作它的实例)
  • 实际上,调用类型对象上的任何方法都具有相同的结果; new不特别
  • 继承它(同样,它适用于自动生成的类)

  • 额外的好处是有人也可以编写它而不是继承。

    其次,class之间没有关系。在 role 内定义和封闭的role (这是一个一般原则:在另一个包中嵌套一个包并不意味着它们之间在对象模型级别上有任何关系)。因此,我们需要使它单独通用并实例化它。

    这两个让我们:
    role BinarySearchTree[::T] {
        my role BinaryNode[::T] is rw {
            has T $.item;
            has BinaryNode $.left;
            has BinaryNode $.right;
        }
    
        method create-node( T $x ) {
            BinaryNode[T].new(item => $x)
        }
    }
    
    my $bst = BinarySearchTree[Int].new;
    $bst.create-node(6);
    

    这确实应该有效,但编译器似乎在 BinaryNode[T] 上弄错了时间。 .我们可以通过强制它将参数化延迟到运行时来解决这个问题;我们有很多方法可以做到这一点,但写作 BinaryNode[$(T)]紧凑且便宜(优化到几乎没有额外成本)。因此给出了一个有效的解决方案:
    role BinarySearchTree[::T] {
        my role BinaryNode[::T] is rw {
            has T $.item;
            has BinaryNode $.left;
            has BinaryNode $.right;
        }
    
        method create-node( T $x ) {
            BinaryNode[$(T)].new(item => $x)
        }
    }
    
    my $bst = BinarySearchTree[Int].new;
    $bst.create-node(6);
    

    关于metaprogramming - 使用捕获的类型来键入类的属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60268760/

    相关文章:

    powershell - 如何将一个PowerShell函数的 'argument-line'传递给另一个函数?

    regex - 如何匹配 perl6 语法中的十六进制数组

    raku - 终端 ANSI 颜色不适用于 Inline::Perl5 (Data::Printer)

    java - 为什么 "TypeToken Collections"被认为是类型安全的? (有效的 Java #29)

    Scala:理解参数多态性

    python使用内部类动态创建类

    ruby - 动态定义模块

    c++ - 使用预处理器对 C/C++ 进行元编程

    string - Perl 6 中的 “P6opaque, Str” 与简单的 “Str” 类型

    haskell - 为什么此功能无法进行类型检查?