Proxee
NAME
Proxee — A more usable Proxy with bells
SYNOPSIS
use Proxee;
General use:
# No self as first arg; simply use a regular block in both code blocks:
my @stuff;
my $stuff := Proxee.new: :STORE{ @stuff.push: $_ }, :FETCH{ @stuff.join: ' | ' }
$stuff = 42;
$stuff = 'meow';
say $stuff; # OUTPUT: «42 | meow»
# Single block as arg; keep all related bits in one place
my $stuff2 := Proxee.new: {
my @stuff;
:STORE{ @stuff.push: $_ },
:FETCH{ @stuff.join: ' | ' }
}
$stuff2 = 42;
$stuff2 = 'meow';
say $stuff2; # OUTPUT: «42 | meow»
Special shared dynamic variable:
# Or just use the special shared variable:
my $stuff2 := Proxee.new: :STORE{ $*PROXEE.push: $_ }, :FETCH{ $*PROXEE.join: ' | ' }
$stuff2 = 42;
$stuff2 = 'meow';
say $stuff2; # OUTPUT: «42 | meow»
# Default STORErer
my $cuber := Proxee.new: :FETCH{ $*PROXEE³ };
$cuber = 11;
say $cuber; # OUTPUT: «1331»
# Default FETCHer
my $squarer := Proxee.new: :STORE{ $*PROXEE = $_² };
$squarer = 11;
say $squarer; # OUTPUT: «121»
# Shortcut to assign to $*PROXEE
my $squarer := Proxee.new: :PROXEE{ $_² };
$squarer = 11;
say $squarer; # OUTPUT: «121»
Coercers (for backward compatibility only):
# Coercer types on variables:
my $integral := Proxee.new: Int();
$integral = ' 42.1e0 ';
say $integral; # OUTPUT: «42»
# Coercer types on attributes:
class Foo {
has $.foo is rw;
submethod TWEAK (:$foo) { ($!foo := Proxee.new: Int()) = $foo }
}
my $o = Foo.new: :foo('42.1e0');
say $o.foo; # OUTPUT: «42»
$o.foo = 12.42;
say $o.foo; # OUTPUT: «12»
Note: this option is only provided for backwards compatibility. Recent version of Rakudo support coercion types out of the box in variable, parameter and attribute declarations.
DESCRIPTION
The core Proxy type is a bit clunky to use. This module provides an alternative class Proxee
with an improved interface, and with a few extra features.
METHODS
new
multi method new(\coercer where {.HOW ~~ Metamodel::CoercionHOW})
multi method new(:&PROXEE, :&STORE, :&FETCH)
multi method new(&block)
Creates and returns a new Proxy object whose :STORE
and :FETCH
Callable
s have been set to behave like functionality offered by Proxee
. Possible arguments are:
An Improved Proxy
The regular functionality of a Proxy remains, except the Proxy
object is no longer passed to neither :FETCH
nor :STORE
callables. :FETCH
gets no args; :STORE
gets 1 arg, the value being stored:
my @stuff;
my $stuff := Proxee.new: :STORE{ @stuff.push: $_ }, :FETCH{ @stuff.join: ' | ' }
$stuff = 42;
$stuff = 'meow';
say $stuff; # OUTPUT: «42 | meow»
In addition, automated storage is available. Assign (do not bind, or you'll break it) to $*PROXEE
variable to store the value in the automated storage and read from it to retrieve that value:
my $stuff2 := Proxee.new:
:STORE{ $*PROXEE.push: $_ },
:FETCH{ $*PROXEE.join: ' | ' }
$stuff2 = 42;
$stuff2 = 'meow';
say $stuff2; # OUTPUT: «42 | meow»
The :STORE
argument is optional and defaults to { $*PROXEE = $_ }
. The :FETCH
argument is optional and defaults to { $*PROXEE }
. The :PROXEE
argument is like :STORE
, except it also assigns itsi return value to $*PROXEE
:
my $squarer := Proxee.new: :PROXEE{ $_² };
$squarer = 11;
say $squarer; # OUTPUT: «121»
Attempting to use both :PROXEE
and :STORE
arguments at the same time will throw Proxee::X::CannotProxeeStore
exception.
A Callable
You can also pass a single codeblock as an argument. It will be evaluated and its return value will be used as arguments to Proxee.new
(after slight massaging to make Pair
s in a List
be passed as named args).
This feature exists to make it slightly simpler to use closures with a Proxy:
my $stuff2 := Proxee.new: {
my @stuff;
:STORE{ @stuff.push: $_ },
:FETCH{ @stuff.join: ' | ' }
}
$stuff2 = 42;
$stuff2 = 'meow';
say $stuff2; # OUTPUT: «42 | meow»
The above is equivalent to:
my $stuff2 := do {
my @stuff;
Proxee.new: :STORE{ @stuff.push: $_ },
:FETCH{ @stuff.join: ' | ' }
}
$stuff2 = 42;
$stuff2 = 'meow';
say $stuff2; # OUTPUT: «42 | meow»
Watch out you don't accidentally pass a block that would be interpreted as a Hash
:
Proxy.new: { :STORE{;}, :FETCH{;} } # WRONG; It's a Hash
Proxy.new: -> { :STORE{;}, :FETCH{;} } # RIGHT; It's a Block
Coercer
Pass a coercer as a positional argument to create a coercing proxy that coerces stored values to specified type:
my $Cool-to-Int := Proxee.new: Int(Cool);
$Cool-to-Int = ' 42.70 ';
say $Cool-to-Int; # OUTPUT: «42»
$Cool-to-Int = Date.today
# OUTPUT: «Type check failed in Proxee; expected Cool but got Date (Date)»
Note: none of :&PROXEE
, :&STORE
, :&FETCH
can be used together with the coercer argument.
Note: this option is only provided for backwards compatibility. Recent version of Rakudo support coercion types out of the box in variable, parameter and attribute declarations.
my Int(Cool) $Cool-to-Int = ' 42.70';
say $Cool-to-Int; # OUTPUT: «42»
$Cool-to-Int = Date.today
# OUTPUT: «Type check failed in Proxee; expected Cool but got Date (Date)»
AUTHOR
Zoffix Znet
COPYRIGHT AND LICENSE
Copyright 2017 - 2018 Zoffix Znet
Copyright 2019 - 2022 Raku Community
This library is free software; you can redistribute it and/or modify it under the Artistic License 2.0.