Perl 6 の does と ^add_role の違い
@kuzuha から素敵情報が届いたので。
@rosylilly gist.github.com/kuzuha/5477051
— デブ (@kuzuha) April 28, 2013
@rosylilly add_role は破壊的ではない。remove_role はない。
— デブ (@kuzuha) April 28, 2013
面白い。試す。
> class c {}; (c) > role r {method greet { say "hello"; }}; (r) > my $a = c.new.^add_role(r); (r) > $a.greet() hello
いい感じだ。
ただ my $a = c.new.^add_role(r);
の時の (r)
という返り値がどうも気にかかる。
does
の方を使ってみると結果が違う。
> my $b = c.new does r; c+{r}.new()
これはこれは……
> class c {method hello { say "hello"; } }; (c) > role r {method hi { say "hi"; } }; (r) > (c.new does r).hello(); hello
動く
> (c.new.^add_role(r)).hello() Method 'hello' not found for invocant of class 'r'
動かない。 oh...
ついでに比較もしておく。
> my $a = (c.new); c.new() > my $b = $a does r; c+{r}.new() > $a eq $b True > $a c+{r}.new()
does
は破壊的操作なので同値になる。まぁ、そりゃそう。
> my $d = $a.^add_role(r); (r) > $a eq $d use of uninitialized value of type r in string context in any at src/gen/Metamodel.nqp:1352 False
つらたん。
そんでもって動的に role を追加する方法を考えるとこんな感じになる。
> class c {}; (c) > role r {}; (r) > my $instance = c.new c.new() > my $role = r (r) > $instance does $role c+{r}.new()
当たり前だけど does
は破壊的操作なので取り外せない。 unextend
的な C 拡張か、言語仕様の拡張を作る必要がある。