(defmspec $protect (&rest x)
(mapcar #'(lambda (s)
(cond ((symbolp s)
(if (get s 'assign)
(mtell "The variable ~:M is already protected" s)
(putprop s 'user-protected 'assign)))
(t
(mtell "Cannot protect ~:M" s)))) (cdar x))
'$done)
(defun user-protected (x y)
(declare (ignore y))
(merror "Cannot assign a value to the protected variable ~:M" x))
(defmspec $unprotect (&rest x)
(mapcar #'(lambda (s) (if (and (symbolp s) (eq 'user-protected (get s
'assign)))
(remprop s 'assign)
(mtell "Cannot unprotect ~:M" s))) (cdar x))
'$done)
Demo:
(C1) load("/home/barton/maxima/protect.lisp")$
(C2) unk : 1$
(C3) protect(unk)$
(C4) unk;
(D4) 1
(C5) unk : 3;
Cannot assign a value to the protected variable unk
-- an error. Quitting. To debug this try DEBUGMODE(TRUE);)
(C6) unprotect(unk)$
(C7) unk : 3;
(D7) 3
(C8) unprotect(values);
Cannot unprotect VALUES
(D8) DONE
(C9) values : 1;
Improper value assignment to VALUES
-- an error. Quitting. To debug this try DEBUGMODE(TRUE);)
(C10)
Changes:
(1) A user can only unprotect a symbol that has the 'user-protected
property; a user is no longer able to unprotect members infolists.
(2) Protect and unprotect no longer evaluate their arguments.
(3) Protect and unprotect now return done instead of true. I think
this is better.
Bugs:
(1) Protection only protects against assignment; a user can make
assumptions on a protected symbol.
(2) Protect is global -- I think fixing this would require lots of
changes to Maxima.
(C1) f(x) := block([y : 0], protect(y),x);
(D1) f(x) := BLOCK([y : 0], PROTECT(y), x)
(C2) f(5);
(D2) 5
(C3) y : 5;
Cannot assign a value to the protected variable y
-- an error. Quitting. To debug this try DEBUGMODE(TRUE);)
(C4)
Other:
I'm undecided whether including this protect / unprotect scheme
would be good or bad for Maxima.
Barton
PS Reading the mset source I learned of the undocumented
option variable SUBSCRMAP
(C1) subscrmap : true;
(D1) TRUE
(C2) [a,b] : 1;
(D2) [1, 1]
(C3) a;
(D3) 1
(C4) b;
(D4) 1
(C5) [a,b] : [x,y];
(D5) [[x, y], [x, y]]
(C6) a;
(D6) y
(C7) b;
(D7) y
This is very odd -- the assignment mapping uses outermap1.
Macsyma eliminated subscrmap and made [a,b] : [x,y] equivalent
to a : x, b : y.