Hubertus van Dam
Hubertus van Dam

Reputation: 11

Maxima: piece='at always evaluates to false

I want to differentiate an expression and generate Fortran for the result. The expression is similar to at(diff(x^2*f(x,y)+y^2*g(x,y),y),x=y). The result contains terms such as at(diff(f(x,y),y),x=y) and at(diff(g(x,y),y),x=y).

Before I generate Fortran I want to remove the at-functions (I have another script to convert the diff(f(x,y),y) and diff(g(x,y),y) entities to subroutine calls). Hence I am trying to write a function that goes through the expression tree and does something special when the at-function is found. However, if I compare piece='at, this always evaluates to false whereas if I compare piece='sin, the sin function is detected correctly. I am completely at a loss as to why the at-function is not detected.

The code I have so far is

eliminateAt(expression) :=
  block( [ops,args,result],
        if atom(expression)
          then expression
          else
             ( ops:  op(expression),
               args: args(expression),
               print("piece=",piece),
               if piece='at
               then processAt(first(args))
               else
                  (
                    result: [],
                    for arg in args do (
                       result: endcons(eliminateAt(arg),result)
                    ),
                    apply(ops,result)
                  )
             )
       );
processAt(expression) :=
   block( [ops,args,result],
          print("expression=",expression),
          expression
        );

If I run this as

eliminateAt(at(diff(f(x,y),y),x=y));

I get

(%i4) eliminateAt(at(diff(f(x,y),y),x=y));
piece= at
piece= derivative
piece= f
piece= =
                                          !
                              d           !
(%o4)                         -- (f(x, y))!
                              dy          !
                                          !x = y

So even though piece is printed to be "at" the function processAt is never called. If I change the line "if piece='at" to "if piece='sin" and then evaluate

eliminateAt(sin(diff(f(x,y),y)));

I get

(%i6) eliminateAt(sin(diff(f(x,y),y)));
piece= sin
            d
expression= -- (f(x, y))
            dy
                                 d
(%o6)                            -- (f(x, y))
                                 dy

which clearly demonstrates that the sin-function is detected no problem. So what is special about the at-function and how can I detect when I have reached it in an expression?

Upvotes: 1

Views: 90

Answers (1)

Robert Dodier
Robert Dodier

Reputation: 17585

The problem you have encountered is that when you write 'at by itself, that symbol is the so-called verb form of at, while if you write 'at(...), then that symbol is the so-called noun form. (Yes, that's subtle and confusing.) You can get the noun form by itself by writing nounify('at).

But a better way in general to handle problems such as this in which you want to replace stuff in an expression tree is to use matchdeclare and defrule or defmatch.

Upvotes: 1

Related Questions