class Point {
field $x :param :reader;
field $y :param :reader;
method as_string() {
return "($x,$y)";
}
}
my $origin = Point->new( x => 0, y => 0 );
say $origin->as_string;
I know which of the two I'd rather write :) package Point {
use Moose;
use overload '""' => \&Str, fallback => 1;
use Moose::Util::TypeConstraints;
subtype "PointLimit" => as 'Num'
=> where { $_ >= -10 && $_ <= 10 }
=> message { "$_ must be a Num between -10 and 10, inclusive" };
has [qw/x y/] => (
is => 'rw',
isa => 'PointLimit',
required => 1,
);
sub Str {
my $self = shift;
return sprintf "[%f,%f]" => $self->x, $self->y;
}
}
raku: class Point {
subset PointLimit of Rat where -10.0 .. 10.0;
has PointLimit $.x is rw is required;
has PointLimit $.y is rw is required;
}
And for those who don't "grok" the above, here it is in Python 3, just so you can see how clean raku's OO syntax is: class PointLimit:
def __init__(self, name):
self.name = name
def __get__(self, point, owner):
return point.__dict__.get(self.name)
def __set__(self, point, value):
if not -10 < value < 10:
raise ValueError('Value %d is out of range' % value)
point.__dict__[self.name] = value
class Point:
x = PointLimit('x');
y = PointLimit('y');
def __init__(self, x, y):
self.x = x
self.y = y
def __str__(self):
return "[%f,%f]" % (self.x, self.y)
For those who are curious, here's a very brief introduction to ECS: https://dev.to/ovid/the-unknown-design-pattern-1l64