green's functions, passing functions to a routine



On Sun, Sep 7, 2008 at 10:35 PM, John Lapeyre <pdl at johnlapeyre.com> wrote:

> > Maxima is inconsistent about whether or not to evaluate the name
> > of a function. If f is already the name of a function, then f is not
> > evaluated in the expression f(t); but it is evaluated otherwise.
> > I'm going to guess that you have a function named f somewhere
> > in your program. An easy workaround is to name the formal argument
> > something obscure like f% or whatever.
>
> I have been looking for an at least quasi-robust solution that doesn't
> involve choosing ugly function names. Using apply rather than
> a function call seems to protect against premature evaluation...
>

Premature evaluation has nothing to do with it.  The issue is that if 'f' is
a defined function, then f(x) always calls the defined function.  Only if f
is *not* a defined function does the evaluator look at the value of f.  This
is a common approach in what Rich Gabriel dubbed Lisp-2's, where there is a
separate function cell and value cell (see
http://www.nhplace.com/kent/Papers/Technical-Issues.html)

There are advantages and disadvantages to this approach. The big advantage
is that a local variable cannot override an important function -- something
which is potentially very pernicious in a dynamic binding system -- it would
make it almost impossible to compile code effectively if, say, 'map' were
potentially overridden everywhere.  In a static binding system, this is of
course much less of a concern.  But Maxima was designed before Scheme, which
was the first major Lisp to use static binding. (And yes, this is certainly
something we are trying to change over time...)  Anyway, let's talk about
Maxima's current behavior.

Maxima has, in fact, at least one more namespace, hasharrays:

   f(x):='fun$
   f[x]:='arr$
   f: 'val$
   block([f:foo],[f(2),f[2],f]) =>  [fun, arr, foo]

An easy way to guarantee that you are using the value and not the functional
value is (+f)(...):

   block([f:foo],[f(2),f[2],f]) =>  [fun, arr, foo, foo()]

I wish that Maxima would do the same for (f)(...), but it does not.

The other alternative is, as Robert says, some sort of convention, e.g.
calling functional arguments %f or whatever.

           -s


> fold(f,x,v) := block([res],
>  res:apply(f,[x,v[1]]),
>  for a in rest(v,1) do
>  res:apply(f,[res,a]),res);
>
> Then I can do this and it works.
>
> (%i26) f(x) := x$
> (%i27) fold(g,x,[a,b,c]);
> (%o27) g(g(g(x,a),b),c)
>
> If instead I call f like f(res,a) in fold, rather than using
> apply, then I get :
>
> (%i15) fold(g,x,[a,b]);
> Too many arguments supplied to f(x):...
>
> because it is trying to call f(x):=x
>
> I have been trying various combinations of single and
> double quotes, eg,
> fold('f,x,v) := ...,
> but I have not found another solution.
>