Kann ich im Org-Modus einen gemeinsamen Codeblock in zwei verschiedene Codeblöcke einschließen?

12

Ich habe eine org-modeDatei mit einer Datentabelle und zwei Python-Codeblöcken, um verschiedene Zusammenfassungen daraus zu extrahieren.

Ich möchte einige gemeinsame Konstanten und Funktionen zwischen diesen beiden Codeblöcken teilen. Im Idealfall würde ich dazu den gemeinsamen Code in einen separaten Codeblock zerlegen, der automatisch einbezogen und ausgewertet wird, wenn einer der beiden anderen Blöcke ausgewertet wird. In der erfundenen Syntax würde es ungefähr so ​​aussehen:

#+NAME: init_block
#+BEGIN_SRC python
  ... common constants and functions here ...
#+END_SRC

#+NAME: summary_1
#+BEGIN_SRC python :prepend init_block
  ... data-processing code depending on init code goes here ...
#+END_SRC

#+NAME: summary_2
#+BEGIN_SRC python :prepend init_block
  ... more processing which also depends on init code ...
#+END_SRC

Ich nehme an, ich könnte die :sessionOption nutzen, würde es aber aus zwei Gründen vorziehen, nicht zu tun. Erstens wird ein statusbehaftetes System eingerichtet und nicht ein System, das jedes Mal neu gestartet wird, wenn ich C-c C-ceinen Codeblock verwende. Zweitens und damit verbunden muss ich jetzt daran denken, den gemeinsamen Initialisierungscode bei jedem Öffnen der Datei manuell auszuwerten: Ich kann nicht einfach die Datentabelle C-c C-caktualisieren, sondern in einen der Zusammenfassungsblöcke gehen und auf klicken, um ihn zu aktualisieren.

Gibt es eine gute Möglichkeit, dies zu tun?

Jon O.
quelle

Antworten:

15

Sie können dies am einfachsten mit der noweb-Referenzsyntax von org-babel für die Erstellung von Lese- und Schreibprogrammen tun . Hier ist ein Beispiel:

* Initialization block containing function definition
#+NAME: init_block
#+BEGIN_SRC python
  constant=19
  def some_function(x):
    return constant * x
#+END_SRC

* Call the function on an integer
#+BEGIN_SRC python :noweb yes 
  <<init_block>>
  return some_function(13)
#+END_SRC

#+RESULTS:
: 247

* Call the function on a string
:PROPERTIES:
:noweb:    yes
:END:

#+BEGIN_SRC python
  <<init_block>>
  return some_function('abc')
#+END_SRC

#+RESULTS:
: abcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabc
veraltet
quelle
Vielen Dank. Das sieht gut aus, viel besser als meine hackische Lösung. Ich werde es in den nächsten Tagen ausprobieren und sehen, ob ich irgendwelche Probleme habe.
Jon O.
@ JonO. Wenn diese Antwort für Sie funktioniert, akzeptieren Sie sie bitte als korrekt - danke
veraltet
4

Nachdem ich ein wenig nachgedacht hatte, fand ich eine Teillösung für dieses Problem. Es funktioniert :session, aber ich kann zumindest sicherstellen, dass der gemeinsame Initialisierungscode immer automatisch ausgeführt wird, bevor einer der anderen Blöcke ausgewertet wird. Der 'Trick' besteht darin, eine Dummy-Header-Variable zu verwenden, die auf den Header-Block verweist und ihn jedes Mal auswertet:

#+NAME: init_block
#+BEGIN_SRC python :session t
  constant=19
  def some_function(x):
    return constant * x
#+END_SRC

#+BEGIN_SRC python :session t :var dummy=init_block
some_function(13)
#+END_SRC

#+RESULTS:
: 247

Jetzt kann ich Definitionen ändern init_blockund sie automatisch neu auswerten lassen, wenn ein anderer Block ausgewertet wird, der auf die Verwendung von verweist :var dummy=init_block. Dies funktioniert gut, sofern die Definitionen in init_blockidempotent und zustandslos sind.

(Beachten Sie, dass Sie beim Ändern von Python-Blöcken in den :sessionModus alle returnAnweisungen entfernen müssen , die im Funktionsmodus erforderlich sind, um einen Wert aus dem Block zurückzugeben.)

Jon O.
quelle