9

In org-mode, I am trying to define a function, a variable, and then assigning to another variable the result of the function call on the first variable. However, then it seems that I cannot use this new variable in subsequent functions calls.

Inlining the function calls does work, but affecting the value to a variable first would allow for faster debug in case something goes wrong in the first function call, and to avoid duplicating potentially expensive computations.

MWE: (use (require 'ob-emacs-lisp) if needed)

#+name: square
#+begin_src emacs-lisp :var x=3
  (message (format "%s" (* x x)))
#+end_src

#+RESULTS: square
: 9

#+name: value
: 45

#+name: squaredvalue
#+call: square(x=value)

#+RESULTS: squaredvalue
: 2025

Now I try to reuse this value: 

#+begin_src emacs-lisp :var res=squaredvalue
  (message res)
#+end_src

#+RESULTS:
: nil

Inlined calls do work:    

#+begin_src emacs-lisp :var res=square(value)
  (message res)
#+end_src

#+RESULTS:
: 2025

Expanding the second code block shows:

(let ((res (quote "nil")))
  (message res))

What am I missing?

(This has been tested on emacs 24.3.1, 24.4 and 24.5, using org 8.2.10)

  • something to do with Babel of Library I think. – yi.tang.uni May 20 '15 at 10:24
7
+50

Explicitly add new #+name: above the #+results: block.

Note: Updated your code from (message res) to (message (format "%s" res)) to prevent a Wrong type argument: stringp, 2025 from causing additional confusion.

#+name: square
#+begin_src emacs-lisp :var x=3 
  (message (format "%s" (* x x)))
#+end_src

#+RESULTS: square
: 9

#+name: value
: 45

#+name: squaredvalue
#+call: square(x=value)

#+name: squaredvalue-results
#+RESULTS: squaredvalue
: 2025

#+begin_src emacs-lisp :var res=squaredvalue
   (message (format "%s" res))
#+end_src

#+RESULTS:
: nil


#+begin_src emacs-lisp :var res=squaredvalue-results
 (message (format "%s" res)) 
#+end_src

#+RESULTS:
: 2025

Tested using
GNU Emacs 24.4.1 (x86_64-unknown-cygwin, GTK+ Version 3.10.9)
Org-Mode Version: 8.2.10

  • Ok, that's definitely the simplest solution to date. In this case, there is actually no need for the #+name: before the #+call: line, so it doesn't add any bookkeeping to the process : just name the results instead of the definition. Maybe it doesn't feel as natural as it could, but at least that's not a work-around begging for an alternative solution. – T. Verron May 26 '15 at 18:46
  • This is nice (+1). I tried it and it works with org-mode 8.2.7c. Interesting that a search of the info documentation of Org Mode for -result returns no results. Please add a note that naming the call is required and that the name of the result must be the name of the call suffixed by -result. At least that is what I noted. (If one misses to name the call the next re-evaluation will add a new result ignoring the existing named result. – Tobias May 26 '15 at 18:55
  • @Tobias - Just to clarify, -result is just a naming convention I used for this example. If you're explicitly looking for the results of a source block then add () to the name when passing the name as a variable to another block or inside a noweb reference. – Melioratus May 26 '15 at 20:37
  • 1
    Looks that the only requirement is that the #+call is named. The name of the result can be chosen arbitrary. If the call is not named an additional unnamed result line is generated by the call. – Tobias May 26 '15 at 20:37
  • Is there any section in the manual that describes that behaviour? – Tobias May 26 '15 at 20:41
3

You can use a :post-routine which outputs the result as :name. Call your babel-block with this post routine and put the result into a drawer. In the following example this post routine is named asValue.

#+name: asValue
#+begin_src emacs-lisp :var name="last" :var val=0 :results drawer
(format "#+NAME: %s\n: %s" name val)
#+end_src

#+name: square
#+begin_src emacs-lisp :var x=3
(message "Running square")
(* x x)
#+end_src

#+RESULTS: square
: 9

#+NAME: value
: 45

#+call: square(value) :post asValue(name="squaredValue",val=*this*) :results drawer

#+RESULTS:
:RESULTS:
#+NAME: squaredValue
: 2025
:END:

Now I try to reuse this value: 

#+begin_src emacs-lisp  :var res=squaredValue
  (format "Re-used value: %s" res)
#+end_src

#+RESULTS:
: Re-used value: 2025

Another way to avoid re-calculation of code blocks is the :cache header argument. If this is set to yes the code block and its arguments are checked for changes and if there are no changes the previous result is used without re-evaluation of the source code block.

* Running of source blocks with caching

#+name: square
#+begin_src emacs-lisp :cache yes :var x=4
(message "Running square")
(* x x)
#+end_src

#+RESULTS[31bcff57ec9977f9b237fdc62ab18b1378b8c646]: square
: 16

#+NAME: value
: 40

#+name: squaredValue
#+begin_src emacs-lisp :cache yes :var x=square(x=value)
x
#+end_src

#+RESULTS[f90a5856e446c3120f7e91c4b77959598078526e]: squaredValue
: 1600

Now I try to reuse this value: 

#+begin_src emacs-lisp  :var res=squaredValue
  (format "Re-used value: %s" res)
#+end_src

#+RESULTS:
: Re-used value: 1600

Re-trying with call:

#+NAME: value2
: 20

#+NAME: squaredResult
#+call: square(x=value2) :cache yes

#+RESULTS[2f7c47d4c609a1a49ce00b4696afb7b5a5517b97]: squaredResult
: 400

The last version gives the following error with org-mode 8.2.4 in emacs 24.3.1.
(I do not know why.)

Debugger entered--Lisp error: (wrong-type-argument integer-or-marker-p nil)
  org-babel-set-current-result-hash("94ef10d9192a0be25e46238df4cf05389ff69040")
  org-babel-lob-execute(("square(x=value2)" ":cache yes" 0 "squaredResult"))
  • Thanks for the hacks! It seems that both solutions work, but we're somewhat getting away with the "just try it, it'll work the way you expect it to" philosophy of org. If it turns out that there is no other solution, I'll accept the answer. – T. Verron May 25 '15 at 21:49
  • @T.Verron I think the second solution (:cache yes) is the standard solution. It is also described in the org-manual (see section 14.8.2.16 :cache'). It is a pity that it does not smoothly work with #+call. I think this is a bug. The first solution works with #+call` and also has the advantage that it completely decouples code blocks. Even if you edit the first code block and try the second one the first one is not evaluated. (Depending on the task that may be an advantage or an disatvantage. You just have to keep it in mind.) – Tobias May 26 '15 at 4:36
  • I was tired last night, I didn't notice... Even if there was no error at evaluation of the last block, would it really work better than the ones I wrote in the question? After all, the problem is not that it reevaluates the call for each reference (it would be a problem too, and then yes, cache would be the solution), but that I cannot reference it at all. – T. Verron May 26 '15 at 6:33
  • @T.Verron Kyle Meyer is right. The changes orgmode.org/w/… did not make it yet into the trunk. The newest version is here: orgmode.org/w/?p=org-mode.git;a=blob_plain;f=lisp/…. But, maybe, there are incompatible changes... – Tobias May 26 '15 at 7:01
  • @T.Verron Above I meant "stable release" and not "trunk". Sorry about that. You can see my answer 1 as workaround for the missing feature. – Tobias May 26 '15 at 8:15
3

I suspect you just need to upgrade your Org mode. This works on my end (current developmental version of Org) and in general should work as of the tag release_8.3beta. Below is the commit that I think fixes the problem you're describing.

commit 1877652ce0234cf333fa103b5ada08fbf5946ab1
Date:   Wed Nov 13 11:42:40 2013 -0700

    allow reference to named call lines

    * lisp/ob-ref.el (org-babel-ref-resolve): Look for call lines when
      resolving references.

Aside from loading Org from the git repo, another option for running a newer version is to install the ELPA package.

  • Well, I may not use the development version, but that does not mean I have not updated since 2013. I am not that late. ;) To be precise, my org-version is 8.2.10. I have editted the question with this information, where it should have been in the first place. – T. Verron May 25 '15 at 21:39
  • Ooops, sorry about the misinformation. That should be the commit, but it isn't contained in 8.2.10. – Kyle Meyer May 25 '15 at 23:06
  • Would you know where I can find a discussion about this commit? – T. Verron May 26 '15 at 7:18
  • If a discussion about it existed, it would most likely be on the Org mode list, but I didn't find one by searching, and there isn't one referenced in the commit message, so there may not be one. – Kyle Meyer May 26 '15 at 14:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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