С 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: 8.2.10


Хорошо, это определенно самое простое решение на сегодняшний день. В этом случае на самом деле нет необходимости в строке #+name:перед #+call:строкой, поэтому она не добавляет никакой бухгалтерии к процессу: просто назовите результаты вместо определения. Может быть, это не так естественно, как могло бы, но, по крайней мере, это не обходной путь, требующий альтернативного решения.
Т. Веррон

Это хорошо (+1). Я попробовал, и он работает с org-mode 8.2.7c. Интересно, что поиск в информационной документации по режиму Org не дал -resultрезультатов. Пожалуйста, добавьте примечание, что необходимо присвоить имя звонку и что имя результата должно совпадать с именем звонка -result. По крайней мере, это то, что я заметил. (Если кто-то пропустит имя вызова, то при следующей переоценке будет добавлен новый результат, игнорирующий существующий именованный результат.
Тобиас

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

1
Выглядит, что единственным требованием является то, что #+callимя. Название результата можно выбрать произвольно. Если вызов не назван, вызовом генерируется дополнительная безымянная строка результата.
Тобиас

Есть ли в руководстве раздел, описывающий это поведение?
Тобиас

3

Вы можете использовать :post-программу, которая выводит результат как :name. Позвоните в ваш babel-block с помощью этой обычной процедуры и положите результат в ящик. В следующем примере эта пост-процедура называется 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"))

Спасибо за взломы! Кажется, что оба решения работают, но мы несколько сбежали с философией org «просто попробуй, все будет работать так, как ты ожидаешь». Если окажется, что другого решения нет, я приму ответ.
Т. Веррон

@ T.Verron Я думаю, что второе решение ( :cache yes) является стандартным решением. Он также описан в руководстве org (см. Раздел 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`, а также имеет то преимущество, что он полностью разделяет блоки кода. Даже если вы редактируете первый блок кода и пробуете второй первый блок не оценивается. (В зависимости от задачи, которая может быть преимуществом или недостатком. Вы просто должны помнить об этом.)
Тобиас

Я устал вчера вечером, я не заметил ... Даже если бы не было ошибки при оценке последнего блока, действительно ли это сработало бы лучше, чем те, которые я написал в вопросе? В конце концов, проблема не в том, что он переоценивает вызов для каждой ссылки (это тоже было бы проблемой, и тогда да, кеш был бы решением), а в том, что я вообще не могу ссылаться на него.
Т. Веррон

@ Т. Веррон Кайл Мейер прав. Изменения 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, другой вариант запуска более новой версии - это установка пакета ELPA .


Ну, я не могу использовать версию развития, но это не значит , что я не обновлялся с 2013 года я не что поздно. ;)Чтобы быть точным, мой org-version8.2.10. Я отредактировал вопрос с этой информацией, где он должен был быть в первую очередь.
Т. Веррон

Упс, извините за дезинформацию. Это должен быть коммит, но он не содержится в 8.2.10.
Кайл Мейер

Не могли бы вы узнать, где я могу найти обсуждение этого коммита?
Т. Веррон

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