[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [PATCH] Add support for tables in Calc src block :var
From: |
Visuwesh |
Subject: |
Re: [PATCH] Add support for tables in Calc src block :var |
Date: |
Fri, 13 Dec 2024 14:32:11 +0530 |
User-agent: |
Gnus/5.13 (Gnus v5.13) |
[வெள்ளி டிசம்பர் 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)))