|
Warning: this is an htmlized version!
The original is here, and the conversion rules are here. |
;; This file:
;; https://anggtwu.net/bad-foundations/display-delegate.lisp.html
;; https://anggtwu.net/bad-foundations/display-delegate.lisp
;; (find-angg "bad-foundations/display-delegate.lisp")
;; Author: Eduardo Ochs <eduardoochs@gmail.com>
;; See: https://anggtwu.net/eev-maxima.html#display_delegate
;; Licence: Public Domain
;; Version: 2026feb22
;;
;; This file defines the Maxima function `display_delegate', that
;; implements a way to define how certain Maxima objects will be
;; displayed - for example,
;;
;; display_delegate('ccc, 'ccc_translate);
;;
;; tells Maxima that an object like ccc(x,y,z) should be displayed by
;; first running ccc_translate(ccc(x,y,z)) and then delegating the
;; displaying to the result.
;; Index:
;; «.introduction» (to "introduction")
;; «.prototypes» (to "prototypes")
;; «.display_delegate» (to "display_delegate")
;; «.test-macro» (to "test-macro")
;; «.test-maxima» (to "test-maxima")
;; «.test-At2» (to "test-At2")
;; «introduction» (to ".introduction")
;; ==============
;; In the beginning of 2024 I saw that the package `qm-maxima' - in
;; <https://github.com/QMeqGR/qm-maxima> - displayed `bra(a)' as `<a|'
;; and `ket(a)' as '|a>'. I asked some questions in the mailing list,
;; and I explained that I was looking for a way to display the
;; coefficients of power series very compactly... in particular, I
;; wanted this:
;;
;; (%i2) ccc(2,3,4);
;; (%o2) <2:3:4>
;;
;; These are the main messages in the mailing list:
;;
;; (find-maximamsg "58827564 202410 12" "EricMajzoub: qm-maxima package")
;; (find-maximamsg "59114438 202501 04" "Edrx: (displa-def $ket ...)")
;; (find-maximamsg "59114461 202501 04" "RDodier: (defun reform-ccc ...)")
;; (find-maximamsg "59114492 202501 04" "Edrx: that people can test in a Maxima REPL")
;; (find-maximamsg "59114658 202501 04" "RDodier: second attempt")
;;
;;
;; «prototypes» (to ".prototypes")
;; ============
;; Robert Dodier gave me several suggestions, and after many clean-ups
;; and and rewrites I converted his "second attempt" into this first
;; prototype:
#|
* (eepitch-maxima)
* (eepitch-kill)
* (eepitch-maxima)
to_lisp();
(displa-def $aaa dimension-nary ":")
(displa-def $bbb dimension-match "<" ">")
(setf (get '$ccc 'dimension) 'dim-$ccc)
(defun dim-$ccc (o result)
(let ((new-o `(($bbb) (($aaa) ,@(rest o)))))
(dimension new-o result 'mparen 'mparen nil 0)))
(to-maxima)
aaa(2,3,4); /* 2:3:4 */
bbb(aaa(2,3,4)); /* <2:3:4> */
ccc(2,3,4); /* <2:3:4> */
op(ccc(2,3,4)); /* ccc */
|#
;;
;; In the first prototype above when Maxima wants to display
;; `ccc(2,3,4)' the function `dim-$ccc' is called with `o' being
;; `ccc(2,3,4)', and it sets `new-o' to `bbb(aaa(2,3,4))' - using a
;; translation that is hardcoded in Lisp. Here is a way to do that
;; translation in Maxima - the "second prototype":
#|
* (eepitch-maxima)
* (eepitch-kill)
* (eepitch-maxima)
ccc_translate(o) := bbb(apply('aaa, args(o)));
ccc_translate(ccc(2,3,4)); /* bbb(aaa(2,3,4)) */
to_lisp();
(displa-def $aaa dimension-nary ":")
(displa-def $bbb dimension-match "<" ">")
(setf (get '$ccc 'dimension) 'dim-$ccc)
(defun dim-$ccc (o result)
(let ((new-o (mfuncall '$ccc_translate o))) ;; <- new
(dimension new-o result 'mparen 'mparen nil 0)))
(to-maxima)
aaa(2,3,4); /* 2:3:4 */
bbb(aaa(2,3,4)); /* <2:3:4> */
ccc(2,3,4); /* <2:3:4> */
op(ccc(2,3,4)); /* ccc */
|#
;; «display_delegate» (to ".display_delegate")
;; ==================
;; The Maxima function `$display_delegate', defined below, implements
;; a way to define how certain Maxima objects will be displayed - for
;; example,
;;
;; display_delegate('ccc, 'ccc_translate);
;;
;; tells Maxima that an object like ccc(x,y,z) should be displayed by
;; first running ccc_translate(ccc(x,y,z)) and then delegating the
;; displaying to the result.
;;
;; Note that `$display_delegate' "is" a Lisp macro defined in a funny
;; way, that uses `display_delegate-3' and `display_delegate-2' to
;; generate a progn. I find that style easier to understand and to
;; debug than a standard macro.
;;
;; Old version: (find-angg "MAXIMA/displa-delegate.lisp")
;;
(defun display_delegate-3 ($CCC $CCC_TRANSLATE DIM-CCC)
`(progn
;;
(setf (get ',$CCC 'dimension) ',DIM-CCC)
(defun ,DIM-CCC (o result)
(let* ((translated-o (mfuncall ',$CCC_TRANSLATE o))
(op-translated-o (caar translated-o))
(dim-translated-o (get op-translated-o 'dimension))
)
;; (dimension translated-o result 'mparen 'mparen nil 0) ; <- fails in At2! Why?
(funcall (or dim-translated-o #'dimension-function) translated-o result)
))
;;
))
(defun display_delegate-2 ($CCC $CCC_TRANSLATE)
(let ((DIM-CCC (intern (format nil "DIM-~a" (symbol-name $CCC)))))
(display_delegate-3 $CCC $CCC_TRANSLATE DIM-CCC)))
(defun $display_delegate ($CCC &optional $CCC_TRANSLATE)
(if $CCC_TRANSLATE
(eval (display_delegate-2 $CCC $CCC_TRANSLATE))
(setf (get $CCC 'dimension) nil)))
;; «test-macro» (to ".test-macro")
;; ------------
;; These tests show how `$display_delegate' works internally.
;; Compare the results of the calls to `display_delegate-3' and
;; `display_delegate-2' below with the result of the quoted progn
;; and with the code in the "second prototype" above.
#|
* (eepitch-maxima)
* (eepitch-kill)
* (eepitch-maxima)
to_lisp();
(load "display-delegate.lisp")
' (progn
;;
(setf (get '$ccc 'dimension) 'dim-$ccc)
(defun dim-$ccc (o result)
(let ((new-o (mfuncall '$ccc_translate o)))
(dimension new-o result 'mparen 'mparen nil 0)))
;;
)
(display_delegate-3 '$ddd '$ddd_translate 'dim-$ddd)
(display_delegate-3 '$ccc '$ccc_translate 'dim-$ccc)
(display_delegate-2 '$ccc '$ccc_translate)
(to-maxima)
|#
;; «test-maxima» (to ".test-maxima")
;; -------------
;; These tests show how to use `display_delegate'
;; from Maxima.
#|
* (eepitch-maxima)
* (eepitch-kill)
* (eepitch-maxima)
load("display-delegate.lisp");
ccc_translate(o) := bbb(apply('aaa, args(o)));
bbb(aaa(2,3,4)); /* bbb(aaa(2,3,4)) */
ccc_translate(ccc(2,3,4)); /* bbb(aaa(2,3,4)) */
ccc(2,3,4); /* ccc(2,3,4) */
op(ccc(2,3,4)); /* ccc */
display_delegate('ccc, 'ccc_translate);
bbb(aaa(2,3,4)); /* bbb(aaa(2,3,4)) */
ccc_translate(ccc(2,3,4)); /* bbb(aaa(2,3,4)) */
ccc(2,3,4); /* bbb(aaa(2,3,4)) */
op(ccc(2,3,4)); /* ccc */
to_lisp();
(displa-def $aaa dimension-nary ":")
(displa-def $bbb dimension-match "<" ">")
(to-maxima)
bbb(aaa(2,3,4)); /* <2:3:4> */
ccc_translate(ccc(2,3,4)); /* <2:3:4> */
ccc(2,3,4); /* <2:3:4> */
op(ccc(2,3,4)); /* ccc */
display_delegate('ccc); /* deactivate the delegation */
ccc(2,3,4); /* bbb(aaa(2,3,4)); */
|#
;; «test-At2» (to ".test-At2")
;; The "right way" to display antiderivatives is explained here:
;; https://anggtwu.net/maxima-edrxbox.html#antideriv
;; (find-baf "edrxbox-examples.lisp" "antideriv")
;;
;; Sometimes we don't way the display a new object in the "right way" -
;; a "quick way" is enough, like in the example below, that yields:
;;
;; (%i5) o : At2(g(u),u,2,3);
;; ┌ ┐
;; │ | u = 3 │
;; │ │
;; (%o5) │ g(u) | │
;; │ │
;; │ | u = 2 │
;; └ ┘
;; (%i6) [op(o), args(o)];
;; (%o6) [At2, [g(u), u, 2, 3]]
;;
#|
* (eepitch-maxima)
* (eepitch-kill)
* (eepitch-maxima)
load("display-delegate.lisp")$
display_delegate('At2, 'At2_translate);
At2_translate(o) := block(
[fx,x,a,b],
[fx,x,a,b] : args(o),
matrix(["", "|", x=b],
[fx, "|", ""],
["", "|", x=a]))$
o : At2(g(u),u,2,3);
[op(o), args(o)];
|#