W org-babel: jak nazwać wyniki wywołania funkcji i użyć ich ponownie


9

W org-modepróbuję zdefiniować funkcję, zmienna, a następnie przypisanie innej zmiennej wynik wywołania funkcji o zmiennej pierwszy. Wydaje się jednak, że nie mogę użyć tej nowej zmiennej w kolejnych wywołaniach funkcji.

Wstawianie wywołań funkcji działa, ale najpierw wpływanie na wartość zmiennej umożliwi szybsze debugowanie w przypadku, gdy coś pójdzie nie tak w pierwszym wywołaniu funkcji, i uniknie powielania potencjalnie kosztownych obliczeń.

MWE: (użyj w (require 'ob-emacs-lisp)razie potrzeby)

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

Rozwinięcie drugiego bloku kodu pokazuje:

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

czego mi brakuje?

(Zostało to przetestowane na emacs 24.3.1, 24.4 i 24.5, przy użyciu org 8.2.10)


myślę, że ma to coś wspólnego z Babel of Library.
— yi.tang.uni

Odpowiedzi:


7

Jawnie dodaj nowy #+name:powyżej #+results:bloku.

Uwaga: Aktualizacja kodu od (message res)celu (message (format "%s" res)), aby zapobiec Wrong type argument: stringp, 2025od powodując dodatkowe zamieszanie.

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

Testowane przy użyciu
GNU Emacs 24.4.1 (x86_64-unknown-cygwin, GTK + wersja 3.10.9)
Wersja trybu org: 8.2.10


Ok, to zdecydowanie najprostsze jak dotąd rozwiązanie. W tym przypadku tak naprawdę nie ma potrzeby #+name:poprzedzania #+call:wiersza, więc nie dodaje on żadnej księgowości do procesu: wystarczy nazwać wyniki zamiast definicji. Może to nie wydaje się tak naturalne, jak mogłoby, ale przynajmniej nie jest to obejście błagające o alternatywne rozwiązanie.
— T. Verron

To jest fajne (+1). Próbowałem i działa z trybem org 8.2.7c. Ciekawe, że wyszukiwanie w dokumentacji informacyjnej Trybu -resultOrganizacji nie zwraca żadnych wyników. Dodaj notatkę, że nazywanie połączenia jest wymagane, a nazwa wyniku musi być nazwą połączenia z przyrostkiem -result. Przynajmniej tak zauważyłem. (Jeśli nie uda się nazwać połączenia, następna ponowna ocena doda nowy wynik, ignorując istniejący nazwany wynik.
— Tobias

@Tobias - dla wyjaśnienia, -resultto tylko konwencja nazewnictwa, której użyłem w tym przykładzie. Jeśli wprost szukasz wyników bloku źródłowego, dodaj ()go do nazwy, przekazując nazwę jako zmienną do innego bloku lub wewnątrz odwołania do nowegob.
— Melioratus

1
Wygląda na to, że jedynym wymaganiem #+calljest nazwa. Nazwę wyniku można wybrać dowolnie. Jeśli połączenie nie zostanie nazwane, wówczas wywołanie generuje dodatkową nienazwaną linię wyniku.
— Tobias

Czy w instrukcji jest jakaś sekcja opisująca to zachowanie?
— Tobias

3

Możesz użyć :post-routine, która wyświetla wynik jako :name. Zadzwoń do swojego bloku babel przy pomocy tej procedury postu i umieść wynik w szufladzie. W poniższym przykładzie procedura ta została nazwana 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

Innym sposobem uniknięcia ponownego obliczania bloków kodu jest :cacheargument nagłówka. Jeśli jest ustawiony na yesblok kodu, a jego argumenty są sprawdzane pod kątem zmian, a jeśli nie ma zmian, poprzedni wynik jest używany bez ponownej oceny bloku kodu źródłowego.

* 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"))

Dzięki za włamania! Wydaje się, że oba rozwiązania działają, ale w pewnym sensie uciekamy od filozofii „po prostu spróbuj, zadziała tak, jak tego oczekujesz”. Jeśli okaże się, że nie ma innego rozwiązania, zaakceptuję odpowiedź.
— T. Verron,

@ T.Verron Myślę, że drugie rozwiązanie ( :cache yes) jest rozwiązaniem standardowym. Jest to również opisane w podręczniku organizacji (patrz rozdział 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`, a także ma tę zaletę, że całkowicie oddziela bloki kodu. Nawet jeśli edytujesz pierwszy blok kodu i wypróbujesz drugi z nich, pierwszy nie jest oceniany (w zależności od zadania, które może być zaletą lub wadą. Musisz o tym pamiętać).
— Tobias

Byłem zmęczony zeszłej nocy, nie zauważyłem ... Nawet jeśli przy ocenie ostatniego bloku nie wystąpił błąd, czy to naprawdę działałoby lepiej niż te, które napisałem w pytaniu? W końcu problem nie polega na tym, że ponownie ocenia połączenie dla każdego odwołania (to też byłby problem, a następnie tak, rozwiązaniem byłoby buforowanie), ale że w ogóle nie mogę go odwoływać.
— T. Verron

@ T.Verron Kyle Meyer ma rację. Zmiany orgmode.org/w/… nie znalazły się jeszcze w bagażniku. Najnowsza wersja jest tutaj: orgmode.org/w/?p=org-mode.git;a=blob_plain;f=lisp/… . Ale być może nastąpiły niezgodne zmiany ...
— Tobias

@ T.Verron Powyżej miałem na myśli „stabilne wydanie”, a nie „bagażnik”. Przepraszam za to. Możesz zobaczyć moją odpowiedź 1 jako obejście brakującej funkcji.
— Tobias

3

Podejrzewam, że musisz tylko zaktualizować swój tryb Org. Działa to na moim końcu (obecna wersja rozwojowa Org) i ogólnie powinno działać od tagu release_8.3beta. Poniżej znajduje się zatwierdzenie, które moim zdaniem rozwiązuje problem, który opisujesz.

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.

Oprócz ładowania Orga z repozytorium git, inną opcją do uruchomienia nowszej wersji jest instalacja pakietu ELPA .


Cóż, nie mogą korzystać z wersji rozwojowej, ale to nie znaczy, że nie są aktualizowane od 2013 roku nie jestem , że późno. ;)Mówiąc org-versionściślej , moja to 8.2.10. Zredagowałem pytanie z tą informacją, gdzie powinno być na pierwszym miejscu.
— T. Verron,

Ups, przepraszam za wprowadzanie w błąd. To powinno być zatwierdzenie, ale nie jest zawarte w 8.2.10.
— Kyle Meyer,

Czy wiesz, gdzie mogę znaleźć dyskusję na temat tego zatwierdzenia?
— T. Verron

Gdyby istniała dyskusja na ten temat, najprawdopodobniej byłaby na liście trybów Organizacji, ale nie znalazłem jej podczas wyszukiwania i nie ma żadnej wzmianki w komunikacie zatwierdzenia, więc może jej nie być.
— Kyle Meyer
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.