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

내가 무엇을 놓치고 있습니까?

(org 8.2.10을 사용하여 emacs 24.3.1, 24.4 및 24.5에서 테스트되었습니다)


도서관의 바벨과 관련이 있다고 생각합니다.
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 Version : 8.2.10


그것은 현재까지 가장 간단한 해결책입니다. 이 경우 실제로 #+name:이전 #+call:줄이 필요하지 않으므로 프로세스에 부기를 추가하지 않습니다. 정의 대신 결과 이름을 지정하십시오. 어쩌면 그것은 자연스럽게 느낄 수는 없지만 적어도 대안 솔루션을 요구하는 해결 방법은 아닙니다.
T. Verron

이것은 좋습니다 (+1). 나는 그것을 시도하고 org-mode 8.2.7c와 함께 작동합니다. 조직 모드의 정보 문서를 검색하면 -result결과 가 반환되지 않습니다. 통화 이름을 지정해야하며 결과 이름은 접미사가 붙은 통화 이름이어야합니다 -result. 적어도 내가 지적한 것입니다. (전화 이름을 지정하지 못한 경우 다음 재평가는 기존의 명명 된 결과를 무시하고 새로운 결과를 추가합니다.
Tobias

@Tobias-명확히 -result하기 위해이 예제에 사용한 명명 규칙입니다. 소스 블록의 결과를 명시 적으로 찾고 있다면 ()이름을 변수로 다른 블록이나 noweb 참조 내부에 전달할 때 이름에 추가 하십시오.
Melioratus

1
유일한 요구 사항 #+call은 이름 이 있어야합니다 . 결과 이름은 임의로 선택할 수 있습니다. 호출의 이름이 지정되지 않은 경우 호출에 의해 이름이 지정되지 않은 추가 결과 행이 생성됩니다.
Tobias

설명서에 해당 동작을 설명하는 섹션이 있습니까?
Tobias

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

해킹 주셔서 감사합니다! 두 솔루션이 모두 효과가있는 것 같지만 "그냥 시도해보십시오. 원하는 방식대로 작동합니다"라는 철학으로 다소 벗어날 것입니다. 다른 해결책이 없다는 것이 밝혀지면 대답을 받아들입니다.
T. Verron

@ 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` 섹션 과 코드 블록을 완전히 분리한다는 장점이 있습니다. 첫 번째 코드 블록을 편집하고 두 번째 코드 블록을 편집하더라도 첫 번째 코드 블록을 시도하더라도 (이점 또는 단점 일 수있는 작업에 따라 다릅니다. 명심해야합니다.)
Tobias

어제 밤에 피곤했지만 눈치 채지 못했습니다 ... 마지막 블록을 평가할 때 오류가 없더라도 질문에 쓴 것보다 실제로 더 잘 작동합니까? 결국, 문제는 각 참조에 대한 호출을 다시 평가한다는 것이 아니라 문제이기도합니다. 그렇습니다. 캐시가 해결책 일 것입니다. 그러나 전혀 참조 할 수는 없습니다.
T. Verron

@ T.Verron Kyle Meyer가 맞습니다. orgmode.org/w/… 변경 사항 은 아직 트렁크에 들어 가지 않았습니다. 최신 버전은 다음과 같습니다 . orgmode.org/w/?p=org-mode.git;a=blob_plain;f=lisp/… . 그러나 호환되지 않는 변경 사항이있을 수 있습니다 ...
Tobias

@ T.Verron 위의 "안정된 릴리스"를 의미하고 "트렁크"가 아닙니다. 미안합니다. 누락 된 기능에 대한 해결 방법으로 내 대답 1을 볼 수 있습니다.
Tobias

3

조직 모드를 업그레이드해야한다고 생각합니다. 이것은 내 끝 (현재 개발 버전의 조직)에서 작동하며 일반적으로 태그대로 작동해야합니다 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.

git repo에서 Org를로드하는 것 외에도 최신 버전을 실행하는 또 다른 옵션 은 ELPA 패키지설치하는 것 입니다.


글쎄, 난 개발 버전을 사용하지 않을 수 있습니다,하지만 난 아니에요 2013 년 이후로 그게 내가 업데이트하지 않은 것은 아니다 있다는 말. ;)정확히 말하면, org-version8.2.10입니다. 나는이 정보를 사용하여 질문을 편집했습니다. 처음에 있어야했습니다.
T. Verron

죄송합니다. 잘못된 정보에 대해 죄송합니다. 그것은 커밋이어야하지만 8.2.10에는 포함되어 있지 않습니다.
Kyle Meyer

이 커밋에 대한 토론을 어디서 찾을 수 있습니까?
T. Verron

그것에 관한 토론이 존재한다면, 그것은 아마도 조직 모드 목록에있을 것이지만 검색을 통해 찾지 못했고 커밋 메시지에서 참조 된 것이 없으므로 하나도 없을 수도 있습니다.
Kyle Meyer
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.