Subject: multiple assignment stuff in src/mlisp.lisp
From: Robert Dodier
Date: Sat, 24 Feb 2007 14:20:36 -0700
Hello,
I've merged the multiple-assignment code from share/contrib/defstruct.lisp
into src/mlisp.lisp. (But I did not merge the defstruct stuff itself; I think
that is a separate topic.) The current version compiles and run_testsuite
reports no unexpected errors. Here are some examples. These are
derived from comments in the code and a message from Stavros.
(%i1) [a, b]: [b, 2*a];
(%o1) [b, 2 a]
(%i2) [a, b]: [b, 2*a];
(%o2) [2 a, 2 b]
(%i3) [a, b]: [b, 2*a];
(%o3) [2 b, 4 a]
(%i4) [a, b]: [b, 2*a];
(%o4) [4 a, 4 b]
(%i5) [a, b]: [b, 2*a];
(%o5) [4 b, 8 a]
(%i6) [a, b, c] : 100;
(%o6) [100, 100, 100]
(%i7) [a, b, c];
(%o7) [100, 100, 100]
(%i8) (kgcd(a, b) := (while b#0 do [a, b]: [b, remainder(a, b)],
abs(a)), kgcd(11*7*5*3, 17*13*11*7));
(%o8) 77
(%i9) (i:10, j:20, [i, j] : [j, i]);
(%o9) [20, 10]
(%i10) [i, j];
(%o10) [20, 10]
So far, so good. For the remainder, I don't know what is the correct
behavior. Anyway I've copied them here to show the behavior of the
current version.
(%i11) [i, i] : [1, 2];
(%o11) [1, 2]
(%i12) i;
(%o12) 2
(%i13) a : [1, 2, 3, 4];
(%o13) [1, 2, 3, 4]
(%i14) (i : 2, [i, a[i]] : [4, 11]);
(%o14) [4, 11]
(%i15) a;
(%o15) [1, 2, 3, 11]
(%i16) [ a[1], a[2] ] : [ a[3], a[4] ];
(%o16) [3, 11]
(%i17) a;
(%o17) [3, 11, 3, 11]
(%i18) (i:0, [ a[i : i + 1], a[i : i + 1] ] : [ a[i : i + 1], a[i : i + 1] ]);
(%o18) [3, 11]
(%i19) a;
(%o19) [3, 11, 3, 11]
Comments?
Robert
PS.
Index: src/mlisp.lisp
===================================================================
RCS file: /cvsroot/maxima/maxima/src/mlisp.lisp,v
retrieving revision 1.32
retrieving revision 1.33
diff -r1.32 -r1.33
618a619,645
>
> ;; ---------- begin code copied & modified from defstruct.lisp
>
> ;; Check to see if the operator has an mset_extension_operator.
> ;; If so, this says how to do assignments. Examples, a at b:x. Put mset_extension_operator
> ;; of $mrecordassign on the atom $@. To allow [a,b]:[3,4] put op on mlist.
> ;; arguably we could use mget, mfuncall, and $mset_extension_operator and
> ;; allow this to be done at the maxima level instead of lisp.
>
> ;; X is could be something like (($FOO ARRAY) 42), in which case it is meaningful
> ;; to look for an assignment operator associated either with $FOO itself or with
> ;; $FOO's object type, with "object type" = (CAAR (SYMBOL-VALUE '$FOO)).
>
> ((let*
> ((x-value (if (boundp (caar x)) (symbol-value (caar x))))
> (mset-extension-op
> (cond
> ((get (caar x) 'mset_extension_operator))
> ((and
> (not (atom x-value))
> (get (caar x-value) '$defstruct_template)
> (get (caar x-value) 'mset_extension_operator))))))
> (if mset-extension-op
> (return-from mset (funcall mset-extension-op x y)))))
>
> ;; ---------- end code copied & modified from defstruct.lisp
>
621,622d647
< ((and $subscrmap (member (caar x) '(mlist $matrix) :test #'eq))
< (return (outermap1 'mset x y)))
624a650,690
> ;; ---------- begin code copied from defstruct.lisp
>
> ;; The follow code implements PARALLEL LIST assignment.
> ;; it is consistent with commercial macsyma. [a,b,c]:[x,y,z] means
> ;; about the same as a:x, b:y, c:z. Actually it
> ;; evaluates x,y,z BEFORE any assignments to a,b,c, hence parallel.
> ;; Also implemented is [a,b,c]:x which evaluates x once and assigns
> ;; to a,b,c.
> ;; value returned is (evaluated x to ex) [ex,ex,ex].
>
> ;; quiz . [a,b]:[b,2*a]. produces values a=b, b= 2*a.
> ;; re-execute the statement 4 times. what do you get? [4b, 8a]
> ;;
> ;; a neat application of parallel assignment is this version of
> ;; a gcd algorithm (for integers)...
> ;; kgcd(a,b):=(while b#0 do [a,b]:[b,remainder(a,b)], abs(a));
> ;; The extended euclidean algorithm looks even better with parallel
> ;; assignment.
>
> ;; add MLIST to possible operators on the left hand side of
> ;; an assignment statement.
>
> (setf (get 'mlist 'mset_extension_operator) '$mlistassign)
>
> (defmfun $mlistassign (tlist vlist)
> ;; tlist is ((mlist..) var[0]... var[n]) of targets
> ;; vlist is either((mlist..) val[0]... val[n]) of values
> ;; or possibly just one value.
> ;; should insert some checking code here
> (if (and (listp vlist)
> (eq (caar vlist) 'mlist)
> (not (= (length tlist)(length vlist))))
> (merror "Illegal list assignment: different lengths of ~M and ~M." tlist vlist))
> (unless (and (listp vlist)
> (eq (caar vlist) 'mlist))
> (setf vlist (cons (car tlist) ;; if [a,b,c]:v then make a list [v,v,v]
> (make-sequence 'list (1-(length tlist)) :initial-element vlist))))
> (map nil #'mset (cdr tlist)(cdr vlist))
> vlist)
>
> ;; ---------- end code copied from defstruct.lisp