Skip to content

Instantly share code, notes, and snippets.

@zoffixznet

zoffixznet/p6.p6 Secret

Last active November 30, 2017 23:37
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 zoffixznet/82556098ddc3740a6f25e8ab8770860c to your computer and use it in GitHub Desktop.
Save zoffixznet/82556098ddc3740a6f25e8ab8770860c to your computer and use it in GitHub Desktop.
class Proxee {
use MONKEY-GUTS;
proto method new(|) { * }
class Proxee::X::CannotBindStore is Exception {
method message {
'A Proxee cannot use :BIND and :STORE at the same time'
}
}
multi method new(\coercer where {.HOW ~~ Metamodel::CoercionHOW}) {
my \from = coercer.^constraint_type;
my \to = coercer.^target_type;
my $to-name := to.^name;
my $STORAGE;
Proxy.new: :FETCH{ $STORAGE }, STORE => -> $, \v {
die X::TypeCheck.new: :got(v.WHAT), :expected(from), :operation<Proxee>
unless nqp::istype(v, from); # on 2017.11 about 13x faster than ~~
nqp::istype(v, to) ?? ($STORAGE := v)
!! ($STORAGE := v."$to-name"());
$STORAGE
}
}
multi method new (:&BIND, :&STORE, :&FETCH) {
&BIND and &STORE and die Proxee::X::CannotBindStore.new;
my &store := (&STORE || &BIND || { $*PROXEE = $_ });
my &fetch := (&FETCH || { $*PROXEE });
my $proxee := do {
my $storage;
Proxy.new: :FETCH{ $storage }, STORE => -> $, \v { $storage := v }
}
Proxy.new: :FETCH{
my $*PROXEE := $proxee;
fetch
}, STORE => -> $, \v is raw {
my $*PROXEE := $proxee;
store v
}
}}
my $v := Proxee.new: :STORE{ $*PROXEE = (1, 2, 3) }, :FETCH{ $*PROXEE };
$v = 42;
say "Value is {$v.perl}";
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment