使用org-babel,如何命名函数调用的结果并重用它们


9

在中org-mode,我试图定义一个函数,一个变量,然后将对第一个变量的函数调用结果分配给另一个变量。但是,看来我不能在后续的函数调用中使用此新变量。

内联函数调用确实可以,但是首先影响变量的值可以加快调试速度,以防万一在第一个函数调用中出现问题,并避免重复可能昂贵的计算。

MWE :((require 'ob-emacs-lisp)根据需要使用)

#+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

展开第二个代码块将显示:

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

我想念什么?

(已使用org 8.2.10在emacs 24.3.1、24.4和24.5上进行了测试)


我认为这与图书馆Babel有关。
yi.tang.uni 2015年

Answers:


7

#+name:在该#+results:块上方明确添加新的。

注意:将代码从更新为(message res)(message (format "%s" res))以防止Wrong type argument: stringp, 2025引起其他混乱。

#+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

使用
GNU Emacs 24.4.1(x86_64-unknown-cygwin,GTK +版本3.10.9)进行了测试:
组织模式版本:8.2.10


好的,这绝对是迄今为止最简单的解决方案。在这种情况下,实际上不需要在行#+name:前使用#+call:,因此它不会在流程中添加任何簿记:仅命名结果而不是定义。也许感觉并不自然,但这至少不是解决方案,而是寻求替代解决方案。
T. Verron,2015年

很好(+1)。我试过了,它可以在组织模式8.2.7c下工作。有趣的是,在组织模式的信息文档中进行搜索-result不会返回任何结果。请注意,必须命名该呼叫,并且结果名称必须是后缀为的呼叫名称-result。至少我注意到了这一点。(如果有遗漏的名字通话下次再评价将增加一个新的结果,忽略了现有的命名结果。
托比亚斯

@Tobias-澄清-result一下,这只是我在此示例中使用的命名约定。如果您要明确查找源块的结果,则()在将名称作为变量传递到另一个块或在noweb引用中时,将其添加到名称中。
Melioratus 2015年

1
看起来唯一的要求#+call是命名。结果名称可以任意选择。如果呼叫未命名,则呼叫会生成其他未命名结果行。
Tobias

手册中是否有任何部分描述了这种行为?
Tobias

3

您可以使用- :post例程将结果输出为:name。使用此发布例程调用您的babel-block,然后将结果放入抽屉。在下面的示例中,此post例程名为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

避免重新计算代码块的另一种方法是:cache标头参数。如果将此设置为yes代码块,并且检查其参数是否更改,并且没有更改,则使用先前的结果,而无需重新评估源代码块。

* 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"))

感谢您的攻击!似乎这两种解决方案都可以,但是我们在某种程度上摆脱了“尝试一下,它将按照您期望的方式工作”的组织哲学。如果事实证明没有其他解决方案,我将接受答案。
T. Verron,2015年

@ T.Verron我认为第二个解决方案(:cache yes)是标准解决方案。它在组织手册中也有描述(请参阅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`,它还具有将代码块完全分离的优点。即使您编辑第一个代码块并尝试第二个代码块,第一个代码块也是如此。 (取决于任务的优缺点。您只需要记住它即可。)
Tobias

昨晚我很累,我没有注意到...即使在评估最后一块时没有错误,它真的比我在问题中写的还要好吗?毕竟,问题不在于它重新评估了每个引用的调用(这也是一个问题,然后是的,缓存将是解决方案),但是我根本无法引用它。
T. Verron,2015年

@ T.Verron Kyle Meyer是正确的。更改orgmode.org/w/…尚未纳入树干。最新版本在这里:orgmode.org/w/?p=org-mode.git ;a = blob_plain ; f=lisp/…。但是,也许有不兼容的更改...
Tobias 2015年

@ T.Verron上面我的意思是“稳定释放”,而不是“树干”。对于那个很抱歉。您可以将我的答案1视为缺少功能的解决方法。
Tobias

3

我怀疑您只需要升级组织模式即可。这对我有效(当前的Org开发版本),并且通常应该在标签上起作用release_8.3beta。以下是我认为可以解决您正在描述的问题的提交。

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.

除了从git repo加载Org之外,另一个运行较新版本的方法是安装ELPA软件包


好吧,我可能不会使用开发版本,但是,这并不意味着我还没有更新,因为2013年我不是那个迟到。;)确切地说,我org-version是8.2.10。我已经使用此信息编辑了问题,该问题应该放在第一位。
T. Verron,2015年

糟糕,对于错误信息,我们深表歉意。那应该是提交,但是它不包含在8.2.10中。
凯尔·梅尔

您知道在哪里可以找到有关此提交的讨论吗?
T. Verron,2015年

如果存在有关它的讨论,那么很有可能会在组织模式列表中,但是我没有通过搜索找到它,并且在提交消息中没有引用任何一个,因此可能没有一个。
凯尔·梅耶
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.