2

Why does my code generate the error when used with org-table?

No error message when code used outside of org-table

#+NAME: get-country-or-area-name
#+HEADER: :var iso-alpha2-code="ca" 
#+HEADER: :var dc-list='((US . "United States of America") (CA . "Canada") (BR . "Brazil"))
#+BEGIN_SRC elisp 
  (setq s (upcase (substring iso-alpha2-code 0 2)))
  (cdr (assoc-string `,s dc-list)) 
#+END_SRC

#+NAME: Brazil
#+CALL: get-country-or-area-name(iso-alpha2-code="br")

#+RESULTS: Brazil
: Brazil

#+NAME: Canada
#+CALL: get-country-or-area-name(iso-alpha2-code="ca")

#+RESULTS: Canada
: Canada

#+NAME: United-States-of-America
#+CALL: get-country-or-area-name(iso-alpha2-code="us")

#+RESULTS: United-States-of-America
: United States of America

Error generated when called in #+TBLFM:

The error is generated when org-table-calc-current-TBLFM attempts to delete the temporary #+TBLFM: line.

Before:

| ISO Alpha 2 Code | Country or Area Name     |
|------------------+--------------------------|
| BR               |                          |
| CA               |                          |
| US               |                          |
#+TBLFM: $2='(org-sbe get-country-or-area-name (iso-alpha2-code $$1))

After:

| ISO Alpha 2 Code | Country or Area Name     |
|------------------+--------------------------|
| BR               | Brazil                   |
| CA               | Canada                   |
| US               | United States of America |
#+TBLFM: $2='(org-sbe get-country-or-area-name (iso-alpha2-code $$1))
#+TBLFM: $2='(org-sbe get-country-or-area-name (iso-alpha2-code $$1))

Excerpt from *Messages* buffer:

Re-applying formulas to 3 lines… done
Re-applying formulas… done
org-table-calc-current-TBLFM: Wrong type argument: integer-or-marker-p, "US"


Thanks for your help!!


Version Info

org-mode version: 8.3.5
emacs version: GNU Emacs 24.5.1 (x86_64-unknown-cygwin, GTK+ Version 3.14.13)

1 Answer 1

2

Ah, very nice. Remember that elisp is dynamically scoped, so any function that you call can see and overwrite any variable you define, and any function that you write can do the same for any variable defined anywhere in the call stack.

In this case, org-table-calc-current-TBLFM defines two variables s and e to hold the start and end positions of the temporary formula. After the table is recalculated it uses those markers to delete the temporary formula. However, your source block sets s to a string, and this overwrites the marker held by org-table-calc-current-TBLFM. You can see in the error message that it expected a marker and got the string "US".

To fix it, just define your own local variable rather than overwriting someone else's. It's still dynamically scoped, but it will shadow the other variable of the same name and then go away once your source block (aka a function) is done:

#+NAME: get-country-or-area-name
#+HEADER: :var iso-alpha2-code="ca"
#+HEADER: :var dc-list='((US . "United States of America") (CA . "Canada") (BR . "Brazil"))
#+BEGIN_SRC elisp
  (let ((s (upcase (substring iso-alpha2-code 0 2))))
    (cdr (assoc-string s dc-list)))
#+END_SRC
3
  • Maybe using a compiled version of "org-table.el" would solve the problem, but I think that it's a bug. A function like org-table-calc-current-TBLFM which calls org-table-recalculate which, in some way, calls the emacs-lisp interpreter should protect its internal variables (like formula, s,e, etc.) to avoid this kind of beyond understanding problem!
    – duthen
    Commented Sep 19, 2022 at 10:39
  • Compiled code has the same semantics as interpreted code, so it wouldn’t change anything. In fact, he was probably using compiled code all along, since Emacs ships with all the elisp files compiled. However, you are correct that this kind of problem is hard to understand. Early programming languages (such as the first Lisp!) were all dynamically scoped, but it took only a few years for lexical scope to be invented and recognized as superior. Virtually all languages designed since then have only had lexical scope. Emacs Lisp is odd because it started with dynamic and implemented lexical later.
    – db48x
    Commented Sep 19, 2022 at 15:36
  • You're right. I was confusing with the french lisp dialect le_lisp, in which interpreted code is quite dynamic and, unless specified, code is compiled lexically and make variables "disappear" (unreachable by "eval", for example).
    – duthen
    Commented Sep 23, 2022 at 11:36

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.