Scope, assumptions, asksign, context. Was Re: Bug in Maxima 5.30.0



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)))