Posso includere un blocco di codice comune in due diversi blocchi di codice in modalità Org?


12

Ho un org-modefile contenente una tabella di dati e due blocchi di codice Python per estrarre diversi riepiloghi da esso.

Vorrei condividere alcune costanti e funzioni comuni tra questi due blocchi di codice. Idealmente, lo farei inserendo il codice comune in un blocco di codice separato, che verrebbe automaticamente incluso e valutato ogni volta che uno degli altri due blocchi viene valutato. Nella sintassi inventata, sarebbe simile al seguente:

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

Suppongo che potrei usare l' :sessionopzione, ma preferirei non farlo, per due motivi. Innanzitutto, imposta un sistema con stato, piuttosto che uno che gira da zero ogni volta che uso C-c C-csu un blocco di codice. In secondo luogo, e in relazione a ciò, ora devo ricordare di valutare manualmente il codice di inizializzazione comune ogni volta che apro il file: non posso semplicemente aggiornare la tabella dei dati, andare su uno dei blocchi di riepilogo e premere C-c C-cper aggiornarlo.

C'è un buon modo per farlo?

Risposte:


15

Puoi farlo più facilmente usando la sintassi di riferimento noweb di org-babel per la programmazione alfabetica. Ecco un esempio:

* 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

Grazie. Sembra fantastico, molto meglio della mia soluzione di hacking. Lo proverò nei prossimi giorni e vedrò se ho qualche problema.
Jon O.

@JonO. se questa risposta funziona per te, la prego di accettarla come corretta - grazie
deprecata il

4

Dopo aver pensato un po 'di più ho trovato una soluzione parziale a questo problema. Lo usa :session, ma posso almeno assicurarmi che il codice di inizializzazione comune venga sempre eseguito automaticamente prima di valutare uno degli altri blocchi. Il "trucco" consiste nell'utilizzare una variabile di intestazione fittizia che fa riferimento al blocco di intestazione, facendolo valutare ogni volta:

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

Ora posso modificare le definizioni init_blocke farle rivalutare automaticamente ogni volta che viene valutato un altro blocco che si riferisce ad esso utilizzando :var dummy=init_block. Funziona bene a condizione che le definizioni init_blocksiano idempotenti e apolidi.

(Si noti che quando si cambiano i blocchi Python in :sessionmodalità è necessario rimuovere tutte le returnistruzioni, che sono necessarie in modalità funzionale per restituire un valore dal blocco).

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.