Inspired by this blogpost I decided to try and make it possible to have ranges of enum
members that dwim, aka. that contain the actual members and not a stringified form.
This is the result. I'm looking for comments and wether I overlook a pitfall. Also, maybe EnumMember
subset can be expressed in a more performant way?
use Test;
subset EnumMember of Any where .HOW.^name eq "Perl6::Metamodel::EnumHOW";
multi sub infix:<..>( EnumMember $a, EnumMember $b )
{
die "Can only do ranges for members of the same enum" unless $a.WHAT === $b.WHAT;
$a.WHAT.^enum_value_list.grep({ $_ === $a fff $_ === $b })
}
enum Foo ( XA => 17, XB => 19, XC => 2, XD => 17, XE => 1, XF => 99 );
enum Goo < YA YB >;
is-deeply( ( XC..XE ).Array, [XC, XD, XE] );
dies-ok({ XA..YB });
1 Answer 1
Probably, you could do something similar by ...
and succ
.
enum Foo ( XA => 17, XB => 19, XC => 2, XD => 17, XE => 1, XF => 99 );
enum Goo < YA YB >;
XC, *.succ ... XE andthen .say
Thus your example could be rewritten
use Test;
subset EnumMember of Enumeration;
multi sub infix:<..>( EnumMember:D ::T $a, T:D $b ) {
$a, *.succ ... $b
}
multi sub infix:<..>( EnumMember $a, $b ) {
die 'Can only do ranges for members of the same enum'
}
enum Foo ( XA => 17, XB => 19, XC => 2, XD => 17, XE => 1, XF => 99 );
enum Goo < YA YB >;
is-deeply( ( XC..XE ).Array, [XC, XD, XE] );
dies-ok({ XA..YB });
But you get Seq
, not Range
. So I prefer redefine the sequence operator ...
and make a new role instead of a subtype.
use Test;
role EnumMember {};
multi sub infix:<...>( EnumMember:D ::T $a, T:D $b ) {
$a, *.succ ... $b
}
multi sub infix:<...>( EnumMember $a, $b ) {
fail 'Can only do sequence for members of the same enum'
}
multi sub infix:<...>( EnumMember $a, $b ) {
$a ... $b
}
enum Foo does EnumMember ( XA => 17, XB => 19, XC => 2, XD => 17, XE => 1, XF => 99 );
enum Goo does EnumMember < YA YB >;
is (XC ... XE), (XC, XD, XE);
dies-ok { XA ... YB };