Upgrade to Pro — share decks privately, control downloads, hide ads and more …

黒魔術で独自定義のenum型制約を満たす値のリ ストを取得する話

Sponsored · Ship Features Fearlessly Turn features on and off without deploys. Used by thousands of Ruby developers.

黒魔術で独自定義のenum型制約を満たす値のリ ストを取得する話

Avatar for ybrliiu

ybrliiu

May 24, 2019
Tweet

More Decks by ybrliiu

Other Decks in Technology

Transcript

  1. 型情報を取得する Mouse::Util::TypeConstraints では、 find_type_constraint という関数で型情報 (Mouse::Meta::TypeConstraint のインスタンス) を取得できます しかし、このTypeConstraint オブジェクトから得られる情報は、型名と型制約を満たすか満たさ

    ないかを判定するCodeRef くらいです use v5.28; use v5.28; use warnings; use warnings; use utf8; use utf8; use Mouse::Util::TypeConstraints qw( enum find_type_constraint ); use Mouse::Util::TypeConstraints qw( enum find_type_constraint ); use DDP +{ deparse => 1, use_prototypes => 0 }; use DDP +{ deparse => 1, use_prototypes => 0 }; enum RGBColors => qw( red green blue ); enum RGBColors => qw( red green blue ); my $type_constraint = find_type_constraint('RGBColors'); my $type_constraint = find_type_constraint('RGBColors'); say $type_constraint->name; say $type_constraint->name; say 'Pass' if $type_constraint->check('red'); say 'Pass' if $type_constraint->check('red'); # check メソッドで渡された引数が、型制約を満たすかをチェックする関数が入っているインスタンス変数 # check メソッドで渡された引数が、型制約を満たすかをチェックする関数が入っているインスタンス変数 # アクセサを通して取得していないのですでにヤバそうな雰囲気がある # アクセサを通して取得していないのですでにヤバそうな雰囲気がある p ¥$type_constraint->{compiled_type_constraint}; p ¥$type_constraint->{compiled_type_constraint};
  2. Mouse::Util::TypeConstraints ではenum 型の型制約をどのように実装しているのかみてみます sub enum { sub enum { my($name,

    %valid); my($name, %valid); if(!(@_ == 1 && ref($_[0]) eq 'ARRAY')){ if(!(@_ == 1 && ref($_[0]) eq 'ARRAY')){ $name = shift; $name = shift; } } %valid = map{ $_ => undef } %valid = map{ $_ => undef } (@_ == 1 && ref($_[0]) eq 'ARRAY' ? @{$_[0]} : @_); (@_ == 1 && ref($_[0]) eq 'ARRAY' ? @{$_[0]} : @_); # EnumType # EnumType return _define_type 1, $name => ( return _define_type 1, $name => ( as => 'Str', as => 'Str', optimized_as => sub{ optimized_as => sub{ return defined($_[0]) && !ref($_[0]) && exists $valid{$_[0]}; return defined($_[0]) && !ref($_[0]) && exists $valid{$_[0]}; }, }, ); ); } }
  3. やってみましょう use v5.28; use v5.28; use warnings; use warnings; use

    utf8; use utf8; use Mouse::Util::TypeConstraints qw( enum find_type_constraint ); use Mouse::Util::TypeConstraints qw( enum find_type_constraint ); use DDP +{ deparse => 1, use_prototypes => 0 }; use DDP +{ deparse => 1, use_prototypes => 0 }; enum RGBColors => qw( red green blue ); enum RGBColors => qw( red green blue ); my $type_constraint = find_type_constraint('RGBColors'); my $type_constraint = find_type_constraint('RGBColors'); use PadWalker qw( peek_sub ); use PadWalker qw( peek_sub ); my $valid = peek_sub($type_constraint->{compiled_type_constraint})->{'%valid'}; my $valid = peek_sub($type_constraint->{compiled_type_constraint})->{'%valid'}; p [ keys %$valid ]; p [ keys %$valid ];