blocks and modules



On 8/4/10, Sergio Callegari <sergio.callegari at gmail.com> wrote:

> In mathematica, you have two scoping devices, namely block and module.

Maxima variables have dynamic scope, perhaps not suprising
since it is based on 60's Lisp implementations which also had
only dynamic scope (right?). Lexical scope was invented later;
Scheme and Common Lisp have it.

> foo(y):=block([x],find_root(exp(x)+x=y,x,0,1));

How about this. Here's a quick hack to make a block
with lexical scope. Yes, it's quite naive; improvements are welcome.

(defmspec $blex (x)
  (let*
    ((args (cdr x))
     (vars (cdr (car args)))
     (exprs (cdr args))
     (gensym-vars (mapcar #'(lambda (s) (let ((s1 (gensym))) (setf
(get s1 'reversealias) s) s1)) vars))
     (subst-eqns (mapcar #'(lambda (x y) `((mequal) ,x ,y)) vars gensym-vars))
     (gensym-mprogn ($psubstitute `((mlist) , at subst-eqns) `((mprogn) , at exprs))))
    (meval gensym-mprogn)))

and here's an example.

foo (y) := blex ([x], find_root (exp(x) + x = y, x, 0, 1));
foo (2);
 => 0.4428544010023886
foo (x);
 => find_root(%e^x+x = x,x,0.0,1.0)

Note that there are actually 2 distinct x variables; one is the
global x imported via y, and other other is a local variable of blex ...

foo (x);
 =>   find_root(%e^x+x = x,x,0.0,1.0)
%, x = 2; /* binds the global x */
 => 0.4428544010023886

> By using a module rather than a block, mathematica creates variable on
> the fly, so you actually get something like
>
> find_root(%e^x$0134+x$0134=x,x$0134,0.0,1.0)

I dunno. Isn't it considered bad form to leak gensyms like that?
The reverse alias thing in the code for blex tells how to display
the gensyms so you don't get G9293, etc, in displayed stuff.

What is considered the "right thing to do" here?
(i.e. lexical variables escaping from their original context.)
I'm guessing it was worked out decades ago.

I am actually quite interested in equipping Maxima with some
lexical constructs, so if you have some comment, let's hear it.

best

Robert Dodier