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

Reply via email to