Awefully confused about how to write interpolation routines



Hello Daniel,

> so, maybe someone could clarify why
>
> linterp(xs,ys) := a block expression with x unbound that computes interpolated values when evaluated in an environment where x is bound to a number;
>
> is preferred vs
>
> linterp(xs,ys) := lambda([x], same block expression here);

I can see that in some ways returning a lambda expression
would be the natural thing to do. For better or worse, however,
Maxima doesn't know a whole lot about lambda expressions;
they are not entirely equivalent to functions. (For example,
integrate (lambda ([x], x), t, a, b); doesn't yield anything useful.)
I guess this situation is by accident and not by design.

Changing direction -- here are some different implementations
of an interpolation scheme. I've simplified the problem to
constructing  a linear interpolation for just 2 points.
Any calculations that can be carried out just once should
go into calculate_interpolation_parameters (a trivial function,
in this example). Then

linterpolate_expression(xx,yy)::=block(
                               [params
                                 :calculate_interpolation_parameters(
                                  xx,yy)],
                               buildq([params],
                                      block([L:params,dx,dy],
                                            dx:L[2]-L[1],
                                            dy:L[4]-L[3],
                                            L[3]
                                             +(x-L[1])*dy/dx)));

linterpolate_lambda(xx,yy)::=buildq(
                           [e:linterpolate_expression(xx,yy)],
                           lambda([x],e));

linterpolate_function(f,xx,yy)::=buildq(
                             [f,
                              e:linterpolate_expression(xx,yy)],
                             f(x):=e);

calculate_interpolation_parameters(
        xx,yy):=[xx[1],xx[2],yy[1],yy[2]];


With these definitions we get results such as these:

(%i5) linterpolate_expression ([3, 4], [a, b]);
(%o5)                  (b - a) (x - 3) + a

(%i6) linterpolate_lambda ([3, 4], [a, b]);
(%o6)           lambda([x], (b - a) (x - 3) + a)

(%i7) linterpolate_function (FOO, [3, 4], [a, b]);
(%o7)             FOO(x) := (b - a) (x - 3) + a

(%i8) dispfun (FOO);
(%t8)             FOO(x) := (b - a) (x - 3) + a

Which of these you like the best depends on what you
want to accomplish, I guess.

Hope this helps,
Robert Dodier