Scope, assumptions, asksign, context. Was Re: Bug in Maxima 5.30.0
Subject: Scope, assumptions, asksign, context. Was Re: Bug in Maxima 5.30.0
From: Robert Dodier
Date: Sat, 7 Sep 2013 20:07:56 +0000 (UTC)
On 2013-09-06, Stavros Macrakis <macrakis at alum.mit.edu> wrote:
> I'm hoping we can come up with some useful primitives (which may themselves
> be written as macros, as Lisp code, I don't care) which allow users to
> write things like with_posval without running into the various subtle traps
> we all know and love.
OK. Here is another prototype. As you mention, this is less about
with_posval and more about the building blocks. I've made use of blex
which is a naive attempt about a lexical block for Maxima.
(%i2) load (unwind_protect) $
(%i3) load ("blex.lisp") $
(%i4) load ("with_posval.mac") $
(%i5) with_posval (asksign (u), [u]);
(%o5) pos
(%i6) with_posval (integrate (u^k, u, a, b), [k, a, b - a]);
(%o6) b^(k+1)/(k+1)-a^(k+1)/(k+1)
So far, so good, right?
(%i7) e : '(integrate (u^k, u)) $
(%i9) macroexpand (with_posval (e, listofvars (e)));
(%o9) unwind_protect(block(supcontext(g16645),assume_positive(listofvars(e)),
e),killcontext(g16645))
(%i10) ''%;
(%o10) integrate(u^k,u)
Well, that's to be expected ... but one can tell Maxima to try harder.
(%i11) with_posval (ev (e), listofvars (e));
(%o11) u^(k+1)/(k+1)
As expected the assumed facts don't leak out.
(%i12) facts ();
(%o12) []
(%i13) contexts;
(%o13) [initial,global]
Here are examples with k being the same or a distinct symbol.
(%i14) assume (equal (k, -1));
(%o14) [equal(k,-1)]
(%i15) with_posval (integrate (x^k, x), [k]);
(%o15) log(x)
(%i16) blex ([k], with_posval (integrate (x^k, x), [k]));
(%o16) x^(k+1)/(k+1)
Anyway the point of this exercise is to show how an interesting new
function could be constructed.
best
Robert Dodier
PS.
$ cat with_posval.mac
;; copyright 2013 by Robert Dodier
;; I release this work under terms of the GNU General Public License
blex ([expr, vars, ctxt_name, x],
with_posval (expr, vars) ::=
buildq ([expr, vars, ctxt_name : gensym ()],
unwind_protect
(block
(supcontext (ctxt_name),
assume_positive (vars),
expr),
killcontext (ctxt_name))),
assume_positive (vars) := map (lambda ([x], assume (x > 0)), vars));
$ cat blex.lisp
;; blex.lisp -- lexical block for Maxima
;; copyright 2012 by Robert Dodier
;; I release this work under terms of the GNU GPL
;;
;; examples:
;; blex ([n:100], f(x) := n : n + x, g() := display(n));
;; blex ([f], f(x) := 2*x);
;; blex ([a], h(x) := a[x] : 1, i() := arrayinfo(a));
(defmspec $blex (x)
(let*
((args (cdr x))
(vars+inits (cdr (car args)))
(vars (mapcar #'(lambda (e) (if (symbolp e) e (second e))) vars+inits))
(inits (remove-if #'symbolp vars+inits))
(exprs (cdr args))
(gensym-vars (mapcar #'(lambda (s) (let ((s1 (gensym))) (setf (get s1 'reversealias) (or (get s 'reversealias) s)) s1)) vars))
(subst-eqns (mapcar #'(lambda (x y) `((mequal) ,x ,y)) vars gensym-vars))
(gensym-mprog ($psubstitute `((mlist) ,@ subst-eqns) `((mprog) ((mprogn) ,@ inits) ,@ exprs))))
(meval gensym-mprog)))