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

2番目のコードブロックを展開すると、次のようになります。

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

何が欠けていますか?

(これは組織8.2.10を使用してemacs 24.3.1、24.4および24.5でテストされています)


ライブラリのバベルと関係があると思います。
yi.tang.uni 2015年

回答:


7

ブロックの#+name:上に明示的にnewを追加し#+results:ます。

注:コードがから(message res)に更新さ(message (format "%s" res))れ、a 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)を使用してテスト済み
Org-Modeバージョン:8.2.10


OK、これは間違いなくこれまでで最も簡単なソリューションです。この場合、実際には#+name:before #+call:行の必要がないため、プロセスに簿記は追加されません。定義の代わりに結果に名前を付けるだけです。多分それは可能な限り自然に感じられないかもしれませんが、少なくともそれは代替ソリューションを頼む回避策ではありません。
T.ヴェロン

これはいいです(+1)。試してみたところ、org-mode 8.2.7cで動作しました。Org Modeの情報ドキュメントを検索して-resultも結果が返されないのは興味深いことです。呼び出しに名前を付ける必要があること、および結果の名前はのサフィックスが付いた呼び出しの名前でなければならないことに注意してください-result。少なくともそれは私が指摘したことです。1つのミスが呼び出しに名前を付ける場合は(次の再評価は、既存の名前の結果を無視して新しい結果を追加します。
トビアス

@Tobias-明確にするために、-resultこの例で使用した命名規則です。ソースブロックの結果を明示的に探している()場合は、名前を変数として別のブロックまたはnoweb参照内に渡すときに名前に追加します。
Melioratus、2015年

1
唯一の要件は、に#+call名前が付けられていることです。結果の名前は任意に選択できます。呼び出しに名前が付けられていない場合、名前のない追加の結果行が呼び出しによって生成されます。
Tobias

マニュアルにその動作を説明しているセクションはありますか?
トビアス

3

:post結果をとして出力する-routineを使用できます:name。このポストルーチンでバベルブロックを呼び出し、結果を引き出しに入れます。次の例では、このポストルーチンの名前は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"))

ハックをありがとう!どちらのソリューションも機能しているようですが、「試してみれば、期待どおりに機能する」というorgの哲学は、やや離れています。他に解決策がないことが判明した場合は、その答えを受け入れます。
T.ヴァーロン

@ T.Verron 2番目のソリューション(:cache yes)は標準ソリューションだと思います。org-manual(セクション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`を参照)にも記載されており、コードブロックを完全に分離するという利点もあります。最初のコードブロックを編集して2番目のコードブロックを試しても評価されていません(利点やdisatvantageかもしれタスクに応じて、あなただけの心の中でそれを維持する必要があります。。)。
トビアス

昨夜は疲れていたのに気づかなかった...最後のブロックの評価でエラーがなかったとしても、質問で書いたものよりも本当にうまくいくのだろうか?結局のところ、問題は各参照の呼び出しを再評価することではありません(それも問題になるでしょう。そうすれば、キャッシュが解決策になるでしょう)が、私はそれをまったく参照できません。
T. Verron、2015年

@ T.Verron Kyle Meyerは正しいです。orgmode.org/w/…の変更はまだトランクに組み込まれていません。最新バージョンはここにあります:orgmode.org/w/?p=org-mode.git;a=blob_plain;f=lisp / 。しかし、たぶん、互換性のない変更がある...
Tobias

@ T.Verron上記は、「トランク」ではなく「安定したリリース」を意味しました。申し訳ありません。不足している機能の回避策として、私の回答1を見ることができます。
トビアス

3

Orgモードをアップグレードする必要があるだけだと思います。これは私の終わり(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リポジトリからOrgをロードする以外に、新しいバージョンを実行するための別のオプションは、ELPAパッケージインストールすることです。


まあ、私は開発版を使用することはできませんが、それは私はないです2013年以来更新していないという意味ではありませんことを後半。;)正確には、私org-versionは8.2.10です。私はこの情報で質問を編集しました。
T.ヴァーロン

おっと、誤った情報については申し訳ありません。これはコミットになるはずですが、8.2.10には含まれていません。
Kyle Meyer

このコミットについてのディスカッションがどこにあるか知っていますか?
T. Verron、2015年

それについての議論が存在した場合、それはおそらくOrgモードのリストにありますが、検索しても見つかりませんでした。また、コミットメッセージで参照されているものがないため、存在しない可能性があります。
Kyle Meyer
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.