I have a class like this:
class Foo {
method some-method(Str $name) { ... }
}
Simple usage:
my $foo = Foo.new;
$foo.some-method("peter");
Since the "some-method" will be called quite frequently, I'd like to do something to allow users to use it like below:
$foo.peter;
I know FALLBACK will do the job, but it has been used for another method. I tried to define an infix operator:
sub infix:<%>(Foo $foo, $name) {
$foo.some-method($name);
}
The code below works, but the double quote is annoying.
$foo % "peter";
So is there any way to avoid the quote mark? Or any way to simplify the invocation?
RMI (Remote Method Invocation) is a way that a programmer, using the Java programming language and development environment, can write object-oriented programming in which objects on different computers can interact in a distributed network.
RMI stands for Remote Method Invocation. It is a mechanism that allows an object residing in one system (JVM) to access/invoke an object running on another JVM. RMI is used to build distributed applications; it provides remote communication between Java programs.
RMI treats a remote object differently from a non-remote object when the object is passed from one Java virtual machine to another Java virtual machine. Rather than making a copy of the implementation object in the receiving Java virtual machine, RMI passes a remote stub for a remote object.
The RMI architecture is based on a very important principle which states that the definition of the behavior and the implementation of that behavior, are separate concepts. RMI allows the code that defines the behavior and the code that implements the behavior to remain separate and to run on separate JVMs.
As Curt Tilmes already pointed out, you could make your Foo
object act as an Associative
(or Hash
):
class Foo {
method some-method(Str $name) { ... }
method AT-KEY(Str $name) { self.some-method($name) }
}
my $foo = Foo.new;
say $foo<peter>; # same as $foo.some-method("peter")
Of course, the AT-KEY
method can be a multi, so you could play all sorts of tricks with that as well.
class Foo {
method some-method(Str $name) { "$name is ok" }
multi method AT-KEY("peter") { "peter is special" }
multi method AT-KEY(Str $name) { self.some-method($name) }
}
my $foo = Foo.new;
say $foo<peter>; # "peter is special"
say $foo<joe>; # "joe is ok"
There is a way that you can use FALLBACK
for more than one operation, provided they are different in some way.
By checking some property of the object:
class Foo {
# this could be set as part of `new`/`BUILD`
has %!special = ( "peter" => 42 );
multi method FALLBACK ( $name where (%!special{$name}:exists) ) {
%!special{$name}
}
multi method FALLBACK ( $other ) {
$other.tc
}
}
with Foo.new {
say .paul; # Paul
say .peter; # 42
}
This has the potential problem of action-at-a-distance.
With different number or types of arguments:
class Bar {
multi method FALLBACK ( Str:D $name ) {
$name.tc
}
multi method FALLBACK ( Str:D $name, Real:D $number ) {
$name.tc, 1 / $number
}
multi method FALLBACK ( Str:D $name, Str:D $other ) {
$name.tc, $other.uc
}
}
with Bar.new {
say .paul; # Paul
say .peter(42); # Peter, 0.02381
say .peter('Paul'); # Peter, PAUL
}
You can use .[…]
for an Int argument.
class Baz {
method AT-POS ( $arg ) { say "Baz[$arg]" }
}
Baz.new[42,32]; # Baz[42]
# Baz[32]
The built-in postcircumfix:« [ ] »
coerces the arguments to Int, but you could add a new one into the mix.
(There are a bunch of caveats with doing this.)
multi sub postcircumfix:<[ ]> ( Baz:D $b, $a ) is export {
# $b.AT-POS( $a )
$b.some-method( $a )
}
You can use .<…>
for space separated Strs or .{…}
for arbitrary values.
class Other {
multi method AT-KEY ( Str:D $name ){
$name.tc
}
multi method AT-KEY ( Real:D $number ){
1 / $number
}
}
with Other.new {
say $_<peter>; # Peter
say $_.<paul>; # Paul
say .<peter paul>; # Peter Paul
# note that AT-Key got called twice
say $_{42,'peter'}; # 0.02381, Peter
# note that AT-Key got called twice
}
You can make it so that your object is callable.
class Fubar {
multi method CALL-ME ( Str:D $name ){
$name.tc
}
multi method CALL-ME ( Real:D $number ){
1 / $number
}
multi method CALL-ME ( +@args ){
@args.map: {self.CALL-ME($_)}
}
}
with Fubar.new {
say $_('peter'); # Peter
say $_(42); # 0.02381
# this calls the +@args one
say $_('paul',32); # Paul, 0.03125
}
You should really think about your API before doing any of these.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With