[வெள்ளி டிசம்பர் 13, 2024] Visuwesh wrote: > [...] > Some caveats: > > 1. You need to ensure that all the calc-embedded variables that you > use in the formula need to be active and evaluated beforehand. > 2. The calc-embedded var is considered at last after everything else > in org-table-get-constant in the advice. This would be the best > way to go forward. > > It would be nice to lift the restrict in (1) but I think it would be > better to leave it to the user to ensure everything stays updated since > the user may want to use the old value. However, ensuring all the vars > are active and eval-ed would be a royal pain when you're quickly > evaluating a table formula. > > Here's the case I used to test this hack: > > x := 3 > > y := 5 > > z := 5 x - y => 10 > > > | 1 | 20 | > > #+TBLFM: $2=$z*2
OK, this was not so simple as I thought! Consider the following example: x := 3 a := 3 x => 9 y := 5 x := 2 z := 5.2 x - y => 5.4 Update x := 3 and y first. Then update `a' and `z'. `z' will be 10.6. Now update x := 2, and update `z' and `a'. `z' updates to 5.4 as shown above but `a' remains 9! Calc looks for the nearest value of the variable `x' from the definition of `z'. The Elisp variable that stores the var information looks like this: (cdar calc-embedded-active) ([#<buffer scratch.org> #<buffer *Calculator*> #<marker at 289961 in scratch.org> #<marker at 289967 in scratch.org> #<marker at 289960 in scratch.org> #<marker at 289968 in scratch.org> #("x := 3" 0 6 (fontified t)) nil (calcFunc-assign (var x var-x) 3) (var x var-x) nil (calcFunc-assign (var x var-x) 3) nil nil nil nil] [#<buffer scratch.org> #<buffer *Calculator*> #<marker at 289969 in scratch.org> #<marker at 289982 in scratch.org> #<marker at 289968 in scratch.org> #<marker at 289983 in scratch.org> #("a := 3 x => 9" 0 13 (fontified t)) nil (calcFunc-evalto (calcFunc-assign (var a var-a) (* 3 (var x var-x))) 9) (var a var-a) (((var x var-x))) 9 nil nil nil nil] [#<buffer scratch.org> #<buffer *Calculator*> #<marker at 289984 in scratch.org> #<marker at 289990 in scratch.org> #<marker at 289983 in scratch.org> #<marker at 289991 in scratch.org> #("y := 5" 0 6 (fontified t)) nil (calcFunc-assign (var y var-y) 5) (var y var-y) nil (calcFunc-assign (var y var-y) 5) nil nil nil nil] [#<buffer scratch.org> #<buffer *Calculator*> #<marker at 289992 in scratch.org> #<marker at 289998 in scratch.org> #<marker at 289991 in scratch.org> #<marker at 289999 in scratch.org> #("x := 2" 0 6 (fontified t)) nil (calcFunc-assign (var x var-x) 2) (var x var-x) nil (calcFunc-assign (var x var-x) 2) nil nil nil nil] [#<buffer scratch.org> #<buffer *Calculator*> #<marker at 290000 in scratch.org> #<marker at 290021 in scratch.org> #<marker at 289999 in scratch.org> #<marker at 290022 in scratch.org> "z := 5.2 x - y => 5.4" nil (calcFunc-evalto (calcFunc-assign (var z var-z) (- (* (float 52 -1) (var x var-x)) (var y var-y))) (float 54 -1)) (var z var-z) (((var y var-y)) ((var x var-x))) (float 54 -1) nil nil nil nil]) Notice how there are two entries for `x'. Worse still, change x := 3 to x := 3.3 and update it. Evaluating the same expression again now yields three entries for `x'! ([#<buffer scratch.org> #<buffer *Calculator*> #<marker at 289961 in scratch.org> #<marker at 289967 in scratch.org> #<marker at 289960 in scratch.org> #<marker at 289970 in scratch.org> #("x := 3" 0 6 (fontified t)) nil (calcFunc-assign (var x var-x) 3) (var x var-x) nil (calcFunc-assign (var x var-x) 3) nil nil nil nil] [#<buffer scratch.org> #<buffer *Calculator*> #<marker at 289961 in scratch.org> #<marker at 289969 in scratch.org> #<marker at 289960 in scratch.org> #<marker at 289970 in scratch.org> #("x := 3.3" 0 8 (fontified t)) nil (calcFunc-assign (var x var-x) (float 33 -1)) (var x var-x) nil (calcFunc-assign (var x var-x) (float 33 -1)) nil nil nil nil] ... ... [#<buffer scratch.org> #<buffer *Calculator*> #<marker at 289996 in scratch.org> #<marker at 290002 in scratch.org> #<marker at 289995 in scratch.org> #<marker at 290003 in scratch.org> #("x := 2" 0 6 (fontified t)) nil (calcFunc-assign (var x var-x) 2) (var x var-x) nil (calcFunc-assign (var x var-x) 2) nil nil nil nil] ...) Which begs the question: what should be `x'? In any case, the code I posted above had a problem with decimals. The code still picks the first value of VAR that shows up in the list above. (defun vz/calc-embedded-get-var (var) "Return the value of active `calc-embedded' VAR in current buffer." (let* ((info (cdr (assq (current-buffer) calc-embedded-active))) (var-info (seq-find (lambda (x) ;; 9 is the variable name: (var XXX var-XXX) (eq var (nth 1 (aref x 9)))) info)) old-val) (when (and info var-info) ;; This is called the `old-val' in `calc-embedded-update'. ;; This can be nil when the formula isn't evaled I think? ;; (aref VAR-INFO 8) is again repeated in 11th slot when the ;; variable is simply as assignment. (let ((calc-line-numbering)) ;; For the below trick, see `calc-embedded-update' again. (math-format-stack-value (list (or (if (and (consp (setq old-val (aref var-info 11))) (eq (car old-val) 'calcFun-assign)) (car (last old-val)) old-val) ;; 8 is the eval form: (calcFun-evalto ...) or ;; (calcFun-assign ...) (car (last (aref var-info 8)))) 1 nil)))))) (define-advice org-table-get-constant (:around (oldfun name) vz/consider-calc-embedded-var) "Check if NAME is a `calc-embedded' at last." (let ((val (funcall oldfun name))) (if (equal val "#UNDEFINED_NAME") (or (vz/calc-embedded-get-var (intern name)) val) val)))