Mit org-babel, wie man die Ergebnisse eines Funktionsaufrufs benennt und wiederverwendet


9

In org-modeversuche ich, eine Funktion, eine Variable, zu definieren und dann das Ergebnis des Funktionsaufrufs für die erste Variable einer anderen Variablen zuzuweisen. Dann scheint es jedoch, dass ich diese neue Variable nicht in nachfolgenden Funktionsaufrufen verwenden kann.

Das Inlinen der Funktionsaufrufe funktioniert, aber wenn Sie zuerst den Wert einer Variablen beeinflussen, können Sie schneller debuggen, falls beim ersten Funktionsaufruf etwas schief geht, und um zu vermeiden, dass potenziell teure Berechnungen dupliziert werden.

MWE: ( (require 'ob-emacs-lisp)bei Bedarf verwenden)

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

Das Erweitern des zweiten Codeblocks zeigt:

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

Was vermisse ich?

(Dies wurde auf Emacs 24.3.1, 24.4 und 24.5 unter Verwendung von org 8.2.10 getestet.)


etwas, das mit Babel von der Bibliothek zu tun hat, denke ich.
yi.tang.uni

Antworten:


7

Fügen Sie explizit neu #+name:über dem #+results:Block hinzu.

Hinweis: Der Code wurde von (message res)auf aktualisiert, um (message (format "%s" res))zu verhindern, dass a Wrong type argument: stringp, 2025zusätzliche Verwirrung stiftet.

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

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


Ok, das ist definitiv die bisher einfachste Lösung. In diesem Fall ist das #+name:vor der #+call:Zeile eigentlich nicht erforderlich , sodass dem Prozess keine Buchhaltung hinzugefügt wird: Benennen Sie einfach die Ergebnisse anstelle der Definition. Vielleicht fühlt es sich nicht so natürlich an, wie es könnte, aber zumindest ist das kein Workaround, um nach einer alternativen Lösung zu betteln.
T. Verron

Das ist schön (+1). Ich habe es versucht und es funktioniert mit org-mode 8.2.7c. Interessant, dass eine Suche in der Info-Dokumentation von Org Mode -resultnach keine Ergebnisse liefert. Bitte fügen Sie einen Hinweis hinzu, dass die Benennung des Anrufs erforderlich ist und dass der Name des Ergebnisses der Name des Anrufs sein muss, dem ein Suffix hinzugefügt wird -result. Zumindest habe ich das bemerkt. (Wenn man den Anruf nicht benennt, fügt die nächste Neubewertung ein neues Ergebnis hinzu, das das vorhandene benannte Ergebnis ignoriert.
Tobias

@Tobias - Nur zur Verdeutlichung, -resultist nur eine Namenskonvention, die ich für dieses Beispiel verwendet habe. Wenn Sie explizit nach den Ergebnissen ()eines Quellblocks suchen, fügen Sie den Namen hinzu, wenn Sie den Namen als Variable an einen anderen Block oder innerhalb einer noweb-Referenz übergeben.
Melioratus

1
Sieht so aus, als ob die einzige Voraussetzung darin besteht, dass der #+callName benannt ist. Der Name des Ergebnisses kann beliebig gewählt werden. Wenn der Anruf nicht benannt ist, wird vom Anruf eine zusätzliche unbenannte Ergebniszeile generiert.
Tobias

Gibt es einen Abschnitt im Handbuch, der dieses Verhalten beschreibt?
Tobias

3

Sie können eine :post-routine verwenden, die das Ergebnis als ausgibt :name. Rufen Sie Ihren Babel-Block mit dieser Post-Routine auf und legen Sie das Ergebnis in eine Schublade. Im folgenden Beispiel wird diese Post-Routine benannt 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

Eine andere Möglichkeit, eine Neuberechnung von Codeblöcken zu vermeiden, ist das :cacheHeader-Argument. Wenn dies auf yesden Codeblock gesetzt ist und seine Argumente auf Änderungen überprüft werden und keine Änderungen vorliegen, wird das vorherige Ergebnis ohne Neubewertung des Quellcodeblocks verwendet.

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

Danke für die Hacks! Es scheint, dass beide Lösungen funktionieren, aber wir kommen etwas mit der Philosophie von org davon, es einfach so zu versuchen, wie Sie es erwarten. Wenn sich herausstellt, dass es keine andere Lösung gibt, akzeptiere ich die Antwort.
T. Verron

@ T.Verron Ich denke, die zweite Lösung ( :cache yes) ist die Standardlösung. Es wird auch im Organisationshandbuch beschrieben (siehe Abschnitt 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` und hat auch den Vorteil, dass es Codeblöcke vollständig entkoppelt. Auch wenn Sie den ersten Codeblock bearbeiten und den zweiten den ersten versuchen wird nicht bewertet. (Abhängig von der Aufgabe, die ein Vorteil oder ein Nachteil sein kann. Sie müssen es nur im Auge behalten.)
Tobias

Ich war letzte Nacht müde, ich habe es nicht bemerkt ... Selbst wenn es keinen Fehler bei der Bewertung des letzten Blocks gab, würde es wirklich besser funktionieren als die, die ich in der Frage geschrieben habe? Schließlich besteht das Problem nicht darin, dass der Aufruf für jede Referenz neu bewertet wird (es wäre auch ein Problem, und dann wäre der Cache die Lösung), sondern dass ich überhaupt nicht darauf verweisen kann.
T. Verron

@ T.Verron Kyle Meyer ist richtig. Die Änderungen orgmode.org/w/… haben es noch nicht in den Trunk geschafft. Die neueste Version finden Sie hier: orgmode.org/w/?p=org-mode.git;a=blob_plain;f=lisp/… . Aber vielleicht gibt es inkompatible Änderungen ...
Tobias

@ T.Verron Oben meinte ich "stabile Freigabe" und nicht "Kofferraum". Das tut mir leid. Sie können meine Antwort 1 als Problemumgehung für die fehlende Funktion sehen.
Tobias

3

Ich vermute, Sie müssen nur Ihren Org-Modus aktualisieren. Dies funktioniert auf meiner Seite (aktuelle Entwicklungsversion von Org) und sollte im Allgemeinen ab dem Tag funktionieren release_8.3beta. Im Folgenden finden Sie das Commit, das meines Erachtens das von Ihnen beschriebene Problem behebt.

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.

Neben dem Laden von Org aus dem Git-Repo besteht eine weitere Option zum Ausführen einer neueren Version darin, das ELPA-Paket zu installieren .


Nun, ich kann die Entwicklungsversion nicht verwenden, aber das bedeutet nicht, dass ich seit 2013 nicht aktualisiert habe. Ich bin nicht so spät. ;)Um genau zu sein, ist mein org-version8.2.10. Ich habe die Frage mit diesen Informationen bearbeitet, wo sie eigentlich hätte sein sollen.
T. Verron

Hoppla, entschuldigen Sie die Fehlinformationen. Das sollte das Commit sein, ist aber in 8.2.10 nicht enthalten.
Kyle Meyer

Würdest du wissen, wo ich eine Diskussion über dieses Commit finden kann?
T. Verron

Wenn eine Diskussion darüber vorhanden wäre, wäre sie höchstwahrscheinlich in der Liste des Org-Modus enthalten, aber ich habe keine gefunden, indem ich gesucht habe, und es gibt keine, auf die in der Festschreibungsnachricht verwiesen wird, sodass möglicherweise keine vorhanden ist.
Kyle Meyer
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.