Як називати 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

Розширення другого блоку коду показує:

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

Що я пропускаю?

(Це було протестовано на emacs 24.3.1, 24.4 та 24.5, використовуючи org 8.2.10)


Щось із Babel of Library я думаю.
yi.tang.uni

Відповіді:


7

Явно додайте нове #+name:над #+results:блоком.

Примітка. Оновіть код (message res)на, (message (format "%s" res))щоб запобігти появі 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


Гаразд, це, безумовно, найпростіше рішення на сьогоднішній день. У цьому випадку насправді немає необхідності в рядку #+name:перед #+call:, тому він не додає до процесу жодної бухгалтерії: просто назвіть результати замість визначення. Можливо, це не так природно, як це могло, але, принаймні, це не обхід, який благає альтернативного рішення.
Т. Веррон

Це приємно (+1). Я спробував це, і він працює з org-mode 8.2.7c. Цікаво, що пошук інформаційної документації Org Mode для -resultрезультатів не дає результатів. Будь ласка, додайте примітку, що потрібно називати виклик і що ім'я результату повинно бути ім'ям дзвінка з суфіксом -result. Принаймні, це те, що я зазначив. (Якщо пропустити назву виклику, наступна повторна оцінка додасть новий результат, ігноруючи існуючий названий результат.
Тобіас

@Tobias - Просто для уточнення, -resultце лише умова про іменування, яке я використав для цього прикладу. Якщо ви явно шукаєте результати вихідного блоку, тоді додайте ()його до імені, передаючи ім'я як змінну в інший блок або всередині noweb-посилання.
Меліорат

1
Виглядає, що єдина вимога - #+callце ім'я. Найменування результату можна вибрати довільно. Якщо виклик не названий, виклик формується додатковим рядком без назви.
Тобіас

Чи є в посібнику якийсь розділ, який описує таку поведінку?
Тобіас

3

Ви можете використовувати :post-програму, яка видає результат як :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"))

Дякую за хаки! Здається, що обидва рішення працюють, але ми дещо відходимо від "просто спробуй, воно буде працювати так, як ти розраховуєш" філософією орг. Якщо виявиться, що іншого рішення немає, я прийму відповідь.
Т. Веррон

@ T.Verron Я думаю, що друге рішення ( :cache yes) - це стандартне рішення. Він також описаний у посібнику з організації (див. Розділ 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`, а також має перевагу в тому, що він повністю роз’єднує блоки коду. Навіть якщо ви відредагуєте перший блок коду та спробуйте другий перший) не оцінюється. (Залежно від завдання, яке може бути перевагою чи несприятливим фактором. Ви просто повинні мати це на увазі.)
Тобіас

Я втомився вчора ввечері, я не помітив ... Навіть якби не було помилки в оцінці останнього блоку, чи справді це буде працювати краще, ніж ті, про які я написав у запитанні? Зрештою, проблема полягає не в тому, що вона переоцінює виклик для кожної посилання (це також буде проблема, і тоді так, кеш буде рішенням), а в тому, що я взагалі не можу посилатися на неї.
Т. Веррон

@ T.Verron Кайл Мейер має рацію. Зміни orgmode.org/w/… ще не ввійшли в багажник. Найновіша версія тут: orgmode.org/w/?p=org-mode.git;a=blob_plain;f=lisp/… . Але, можливо, є несумісні зміни ...
Тобіас,

@ 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.

Крім завантаження Org з git repo, ще одним варіантом запуску нової версії є встановлення пакета ELPA .


Ну, я не можу використовувати версію розвитку, але це не означає , що я не оновлювався з 2013 року я не що пізно. ;)Якщо бути точним, мій org-version- 8.2.10. Я відредагував питання з цією інформацією, де воно мало бути в першу чергу.
Т. Веррон

Ой, вибачте за дезінформацію. Це має бути зобов'язання, але воно не міститься в 8.2.10.
Кайл Мейєр

Чи знаєте ви, де я можу знайти дискусію з цього приводу?
Т. Веррон

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