type-conversion – Perl6类属性中的类型强制

前端之家收集整理的这篇文章主要介绍了type-conversion – Perl6类属性中的类型强制前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
与Perl5中的大多数内容一样,有许多方法可以创建支持属性自定义类型强制的类.这是一个简单的,从数组引用到哈希:

#!/usr/bin/env perl

package Local::Class {
  use Moo;
  use Types::Standard qw( HashRef ArrayRef );

  has set => (
    is => 'ro',coerce => 1,isa => HashRef->plus_coercions(
      ArrayRef,sub { return { map { $_ => 1} @{$_[0]} } },),);
}

my $o = Local::Class->new({ set => [qw( a b b c )] });
# $o->set now holds { a => 1,b => 1,c => 1}

我一直在尝试将这样的东西移植到Perl6,在我看来我需要的是一种将数组强制转换为SetHash的方法.到目前为止,我能够做到这一点的唯一方法是:

#!/usr/bin/env perl6

class Local::Class {
  has %.set;
  ## Wanted to have
  # has %.set is SetHash;
  ## but it dies with "Cannot modify an immutable SetHash"

  submethod TWEAK (:$set) {
    self.set = $set.SetHash;
  }
}

my $o = Local::Class.new( set => [< a b b c >] );
# $o.set now holds {:a,:b,:c}

但是在我看来这不是正确的方法,至少对于将奇数编号列表传递给构造函数的微小细节会使脚本死亡.

那么,这是如何在Perl6中完成的?有什么建议的方法(因为我确定不止一个)为类属性实现自定义类型强制?

解决方法

TWEAK在BUILD初始化对象之后运行,这就是提供奇数编号阵列会爆炸的地方.

将强制移动到BUILD时间,事情应按预期工作:

class Local::Class {
  has %.set;
  submethod BUILD (:$set) {
    %!set := $set.SetHash;
  }
}

如果您可以将强制SetHash()参数类型与自动属性初始化结合使用会很好,但这会失败,因为sigil是属性名称的一部分,如果您想接受非参数,则参数不能为%-sigilled – 关联类型.

但是,如果您使用$-sigilled属性,它可以正常工作:

class Local::Class {
  has $.set;
  submethod BUILD (SetHash() :$!set) {}
}

正如@smls指出的那样,以下变种

class Local::Class {
  has %.set is SetHash;
  submethod BUILD (:$set) {
    %!set = $set.SetHash;
  }
}

可能应该工作,而不是死亡无法修改不可变的SetHash.

作为SetHash无法分配的解决方法,您可以使用

class Local::Class {
  has %.set is SetHash;
  submethod BUILD (:$set) {
    %!set{$set.SetHash.keys} = True xx *;
  }
}

猜你在找的Perl相关文章