[Prev][Next][Index][Thread]

Neat little hack: dispatching on keyword args



Hi all, 

I've occasionally wanted to write methods that dispatch on keyword
parameters, but this is (rightly) not possible. Anyway, I've found a
simple little trick for working around this.

Suppose I have a method with the following signature

  define method repeat(re :: <regexp>,
  		       #key min :: <integer> = 0,
  			    max :: <infinity-or-int> = $infinity)
    => (new :: <regexp>);

and I want to dispatch on different min and max arguments, calling
different constructors for each posisble case. The hack is to define
the method repeat, and make its body just a call to a helper gf that
has min and max as required positional args, and dispatches on them.

For example: 

  define function repeat(re :: <regexp>,
  		         #key min :: <integer> = 0,
  			      max :: <infinity-or-int> = $infinity)
    => (new :: <regexp>);
    helper(re, min, max)
  end function repeat;
  
  define method helper(re :: <regexp>, min == 0, max == $infinity)
   => (new :: <regexp>)
    re.kleene-closure
  end method helper;
  
  define method helper(re :: <regexp>, min :: <integer>, max == $infinity)
   => (new :: <regexp>)
    make(<re-sequence>, first: re, second: helper(re, min - 1, max))
  end method helper;
  
  define method helper(re :: <regexp>, min == 0, max :: <integer>)
   => (new :: <regexp>)
    helper(re.optional, max, max)
  end method helper;

  [...and so on...]

This is an obvious trick, but I thought I'd share it anyway in case
any of you hadn't seen it before.


Neel