On Tuesday, 24. February 2009 07:30:05 Carl Mäsak wrote: > > my $foo is limited(100..200); > > $foo = 5; # really does $foo = 100 > > Sounds like a good idea for a CPAN module. You can already do > something similar with the subset keyword, though: > > subset Percentage of Int where { 0 <= $^perc <= 100 }; > > sub set_percentage(Percentage $perc is rw, Int $value) { > try { > return $perc = $value; > CATCH { > return $perc = 0 if $value < 0; > return $perc = 100 > } > } > }; > > my Percentage $p; > say set_percentage($p, 50); > say set_percentage($p, 101)
I would use a parametric role to implement that: role Limited[Order ::Type, Order $lower, Order $upper] { multi sub infix:<=> (Limited $lhs is rw, Type $rhs --> Type) { if $rhs before $lower { $lhs.STORE($lower) } elsif $rhs after $upper { $lhs.STORE($upper) } else { $lhs.STORE($rhs) } return $rhs; # provide original for outer scope } } my Limited[Int,0,100] $p; $p = 50; # assigns 50 $p = 101; # assigns 100 This is an interesting example of a role that can be instanciated without a class unless one regards the generated multi target an instance of a code class. I used STORE to avoid an infinite recursion in dispatch of infix:<=>. I could also have called infix:<=>:(Type is rw, Type --> Type) explicitly. This is necessary if it is overloaded as well. I'm unsure if parametric roles work like that, especially the use of Limited inside the sub. This role should be an easy candidate for inline expansion by the compiler. Also the 'is rw' on the first parameter enforces an exact match so there's no need for dynamic dispatch. I assume that an 'is rw' actually dispatches on the declared container type of the lhs. Regards, TSa. -- "The unavoidable price of reliability is simplicity" -- C.A.R. Hoare "Simplicity does not precede complexity, but follows it." -- A.J. Perlis 1 + 2 + 3 + 4 + ... = -1/12 -- Srinivasa Ramanujan