From: Visuwesh <visuweshm@gmail.com>
To: Org Mode List <emacs-orgmode@gnu.org>
Subject: Re: [PATCH] Add support for tables in Calc src block :var
Date: Fri, 13 Dec 2024 14:32:11 +0530 [thread overview]
Message-ID: <87jzc42bxo.fsf@gmail.com> (raw)
In-Reply-To: <87pllw2g4l.fsf@gmail.com> (Visuwesh's message of "Fri, 13 Dec 2024 13:01:38 +0530")
[வெள்ளி டிசம்பர் 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)))
next prev parent reply other threads:[~2024-12-13 9:03 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-03-16 3:45 [PATCH] Add support for tables in Calc src block :var Visuwesh
2024-03-16 9:52 ` Ihor Radchenko
2024-03-16 11:37 ` Visuwesh
2024-03-16 12:19 ` Ihor Radchenko
2024-03-16 12:34 ` Visuwesh
2024-03-18 12:48 ` Fraga, Eric
2024-03-18 15:29 ` Visuwesh
2024-03-18 15:45 ` Fraga, Eric
2024-03-30 13:04 ` Visuwesh
2024-04-03 12:43 ` Fraga, Eric
2024-12-13 7:31 ` Visuwesh
2024-12-13 9:02 ` Visuwesh [this message]
2024-12-13 10:53 ` Fraga, Eric
2024-12-13 11:06 ` Visuwesh
2024-12-13 11:48 ` Fraga, Eric
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
List information: https://www.orgmode.org/
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=87jzc42bxo.fsf@gmail.com \
--to=visuweshm@gmail.com \
--cc=emacs-orgmode@gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this public inbox
https://git.savannah.gnu.org/cgit/emacs/org-mode.git
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).