Чи можу я включити загальний блок коду у два різні кодові блоки в режимі Org?


12

У мене є org-modeфайл, що містить таблицю даних і два блоки коду Python, щоб отримати з нього різні резюме.

Я хотів би поділитися деякими загальними константами та функціями між цими двома кодовими блоками. В ідеалі я б це зробив, розподіливши загальний код на окремий блок коду, який автоматично включатиметься та оцінюється кожного разу, коли будь-який з двох інших блоків оцінюється. У складеному синтаксисі це виглядатиме приблизно так:

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

Я припускаю, що я міг би скористатися цим :sessionваріантом, але я вважаю за краще би не з двох причин. По-перше, він встановлює надзвичайну систему, а не таку, яка працює з нуля кожного разу, коли я використовую C-c C-cкод блоку коду. По-друге, і, відповідно, тепер мені потрібно пам’ятати, щоб кожен раз відкривати файл вручну оцінювати загальний код ініціалізації: я не можу просто оновити таблицю даних, перейти до одного із блоків підсумків та натиснути, C-c C-cщоб оновити його.

Чи є хороший спосіб це зробити?

Відповіді:


15

Це можна зробити найпростіше, використовуючи нотабельний синтаксис nobeb від org-babel для грамотного програмування. Ось приклад:

* 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

Дякую. Це виглядає чудово, набагато краще, ніж моє хакіче рішення. Я спробую це в найближчі кілька днів і побачу, чи є у мене проблеми.
Джон О.

@JonO. якщо ця відповідь працює для вас, тоді ви прийміть її як правильну - спасибі
застарілу

4

Подумавши трохи більше, я знайшов часткове рішення цієї проблеми. Він використовується :session, але я можу принаймні гарантувати, що загальний код ініціалізації завжди запускається автоматично перед оцінкою одного з інших блоків. «Трюк» полягає у використанні фіктивної змінної заголовка, яка посилається на блок заголовка, внаслідок чого його щоразу оцінюють:

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

Тепер я можу змінювати визначення init_blockта автоматично їх переоцінювати, коли оцінюється інший блок, який посилається на нього з використанням :var dummy=init_block. Це добре працює за умови, що визначення в init_blockідентичному і без громадянства.

(Зверніть увагу, що при зміні блоків Python в :sessionрежим ви повинні видалити всі returnоператори, необхідні у функціональному режимі, щоб повернути значення з блоку).

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.