Hello all,
?
According to the manual, rempart(expr, n) removes the nth argument of the first operator of expr.
First? load(functs)$? to load the function, and? lispdisp:true$? will be necessary later.
?
But, as one can see,
?
rempart(x + y + z, 1) ;?? fails because the expression is not a list
?
rempart([1, 2, 3]);???? also fails, saying memory is corrupted.
?
So what happens ?
?
fundef(rempart);
rempart(exp,n) :=
?? ?append(? rest(exp,-length(exp)-1+(if listp(n) then n[1] else n)),
????????????????? block([t],if atom(t:rest(exp,if listp(n) then n[2] else n)) then ?list(t) else ?cdr(t)))
?
So, basically, the function takes the left part, the right part, then concatenates the two with a lisp function (call to ?append)
to keep the right operator (mlist, mplus, etc.). And for the right part, get the cdr to erase the operator first.
?
Something is going wrong though, try this :
?
?append([1, 2], ?cdr([3, 4]));
?append([1, 2], [3, 4]);
?
The first just fails, while the second fails in wxMaxima and print some strange result in xMaxima :
[1, 2, ([, ?simp), 3, 4]
?
Actually, the operator of the second argument is now part of the list and Maxima does not like that very much.
In the former, for some reason, Maxima is upset with ?cdr([1, 2]) which, alone, still fails.
Not that surprising: this is a lisp list, not a valid Maxima object.
?
To verify:
?
a: [1, 2]$
b: [3, 4]$
:lisp (setf $test (append $a (cdr $b)))
?
Then in Maxima test; yeilds [1, 2, 3, 4], as expected (we keep the operator and contents of a,
drop the operator but keep contents of b, so it's merely equivalent to append(a, b) in Maxima.
?
Ultimately, it seems Maxima is not able to use ?cdr, even in intermediate results. Or equivalently,
that it does not know what to do with lisp lists, even in intermediate results.
?
There is an easy workaround though. Just define the problematic operation in pure lisp:
?
:lisp (defun $aux (a b) (append a (cdr b)))
?
rempart(exp, n) := aux(
?? rest(exp, -length(exp) - 1 + (if listp(n) then n[1] else n)),
?? block([t], if atom(t: rest(exp, if listp(n) then n[2] else n)) then [t] else t))$
?
That's for the rempart function on lists. What about general expressions ?
?
There are several difficulties here:
?
1) reading carefully, we see the function checks the second argument: if it's an atom, make it a list so that we can append.
But the first argument has the same problem, so we need a check there too. But we can't simply make it a list when it's an
atom, remember: we need to keep the original operation. And both left and right parts may be empty, so we need a bit more.
?
2) checking if the result of rest is an atom is not the right way to go: rest(x + y, -1) = y is an atom, but
rest((x * z) + y, -1) = x * z is certainly not. We will need to check the positions removed aginast the expression length.
?
3) rest(x + y, 2) = 0, and we don't want to introduce a 0 in an expression. Here maxima
is a bit too clever;? rest(['x, 'y], 2) = [], but when it's not mlist but mplus, the only adequate "null object" is 0.
But if we remove null objects we may end up with just ((mplus simp)), which does not print very well.
Then, if appending 0 to x or x to 0, just remove 0, but if it's 0 and 0, keep one 0 (same thing with mtimes and 1, etc.)
?
4) also, rest([x, y], 1) is a list with one element as needed, whereas rest(x + y, 1) is an atom. So we need to be
very careful when playing with expression parts.
?
Here is a possible solution, though probably not the simplest. It may be also simpler in pure lisp, but I'm not
proficient enough to write it entirely in lisp right now.
We won't keep track of the operators when taking parts, only at the end, by taking the original one
:lisp (defun $aux1 (e a b) (cons (car e) (append (cdr a) (cdr b))))
?
Since we don't care, we convert to a list before taking part (to circumvent pb 4)
?
:lisp (defun $aux2 (a) (cons '(mlist) (cdr a)))
?
rempart(e, n) := block(
?? [p, q, left, right, v: aux2(e), m],
?? m: length(v),
?? if listp(n) then [p, q]: n else p: q: n,
?? if p = 1 then left: [] else left: rest(v, -m + p - 1),
?? if q = m then right: [] else right: rest(v, q),
?? if p = 1 and q = m then right: rest(e, q) else aux1(e, left, right))$
?
Then, hopefully, it does the job.
?
hth