parsing arguments for functions



On 6/4/09, Sheldon Newhouse <sen1 at math.msu.edu> wrote:

>  Suppose I have a function f(x,y) which does different operations for
> different types of arguments.  How can I parse the arguments of f(x,y)
> and decide what properties x and y have?
>
> For instance, the function f(x,y) = x*y already does this, say for x, y
> real numbers or matrices.
>
> How can I do this for other types of arguments?
>
> For instance, consider real closed intervals [a,b] denoted by Interval(a,b).

It turns out Maxima's simplification rule system is pretty well suited ....

  matchdeclare (ii, intervalp, xx, lambda ([e], not intervalp (e)));
  intervalp (e) := not atom (e) and op (e) = 'Interval;
  tellsimpafter (ii * xx, interval_times_noninterval (ii, xx));

  interval_times_noninterval (ii, xx) :=
    if op (ii) = 'Interval
      then Interval (xx * first (ii), xx * second (ii))
      else
       (intervals_product (args (ii)),
        Interval (xx * first (%%), xx * second (%%)));

  intervals_product (L) := tree_reduce (two_intervals_product, L);
  two_intervals_product (I1, I2) := block
   ([a, b, c, d, L],
    [a, b, c, d] : [first (I1), second (I1), first (I2), second (I2)],
    L : [a*c, a*d, b*c, b*d],
    Interval (lmin (L), lmax (L)));

  Interval(1, 2) * Interval(3, 4) * %pi * 2;
  => Interval(6 %pi, 16 %pi)


The bit xx*Interval(a, b) --> Interval(xx*a, xx*b) is correct only when
xx > 0. I've probably messed up other details.

How this works is described in tedious detail in the reference manual
for matchdeclare and tellsimpafter. In particular, tellsimpafter
"sweeps up" arguments for * (and + as well).

tellsimpafter & friends work pretty well for cases like this
(arithmetic operations on a new kind of object); I've done this
for various purposes (e.g. arithmetic on units of measurement,
base 60 notation).

Hope this helps,

Robert Dodier