Skip to content

Instantly share code, notes, and snippets.

@Xliff
Last active December 24, 2018 06:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Xliff/6a438b3e0ab736c0be1c17c952250432 to your computer and use it in GitHub Desktop.
Save Xliff/6a438b3e0ab736c0be1c17c952250432 to your computer and use it in GitHub Desktop.
use v6.c;

class Token {
  has $.type;
  has $!id;

  method id is rw {
    Proxy.new(
      FETCH => -> $ { $!id },
      STORE => -> $, $nv {
        if $nv ~~ $.type {
          $!id = $nv;
        } else {
          die "Not a { $.type.^name } value.";
        }
      }
    );
  }
}

my $inty = Token.new(:type(Int));
my $stry = Token.new(:type(Str));
$inty.id = 10;
say $inty.id;
$stry.id = 'AA';
say $stry.id;
try {
 $inty.id = 'AA';
 CATCH {
   default { .message.say }
 }
}
try {
 $stry.id = 11;
 CATCH {
   default { .message.say }
 }
}

And the armchair explanation:

<Xliff> OK, let me explain.
<Xliff> In Perl6, it's best to leave type constraints until as late as possible.
<lookatme_q> Maybe using the type parameter role
<lookatme_q> https://docs.perl6.org/language/objects#index-entry-Parameterized_Roles
<Xliff> so we start with: "class Token { has $.typel has $!id; ... }
<Xliff> $.type and $!id are not typed. This is important.
<Xliff> Given that $!id means "private member", so we have to create a way to access ID.
<Xliff> Hence "method id is rw".
<Xliff> Saying "$inty = 10" is the same as saying "$inty.STORE(10)"
<Elronnd> ok
<Xliff> Correction... Saying "$inty.id = 10" is the same as saying "$inty.id.STORE(10)"
<Xliff> For the sake of this conversation, at any rate.
<Xliff> So that "10" value is passed to $nv in the STORE part
<Xliff> When we initialized $inty, we did so like this "my $inty = Token.new(:type(Int))"
<Xliff> That created a new Token object with $.type set to the type object Int.
<Xliff> Following?
<Elronnd> yes
<Xliff> So when any Token object sets the id value, it is smartmatched against the type object stored in the type attribute
<Xliff> What is unsaid here is that $!type MUST be a Perl6 type object.
<Xliff> That way it Just Works.
<lookatme_q> m: role Token[::T] { has T $.id; }; say Token[Int].new(id => 123); say Token[Int].new(id => "123");
<camelia> rakudo-moar 83f0fd6c9: OUTPUT: «Token[Int].new(id => 123)␤Type check failed in assignment to $!id; expected Int but got Str ("123")␤  in block <unit> at <tmp> line 1␤␤»
<Elronnd> ahhh ok, that makes sense
<Elronnd> (can we add a setter for $.type to make sure it's a type object? :P)
<lookatme_q> Maybe you can consider the type parameterized role ^^ Elronnd 
<Xliff> Elronnd: lookatme_q Just put up a much more efficient way of doing this with a role
<Xliff> Elronnd: Ah! Good that you mentioned "setter".
<Xliff> What I did in the ID method is pretty much the way you would implement get/set methods in Perl6.
<Xliff> Proxy FETCH ==> gety
<Xliff> Proxy STORE ==> set
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment