Với org-babel, cách đặt tên kết quả của một cuộc gọi hàm và sử dụng lại chúng


9

Trong org-mode, tôi đang cố gắng xác định một hàm, một biến và sau đó gán cho một biến khác kết quả của lệnh gọi hàm trên biến đầu tiên. Tuy nhiên, sau đó có vẻ như tôi không thể sử dụng biến mới này trong các cuộc gọi chức năng tiếp theo.

Nội tuyến các lệnh gọi hàm hoạt động, nhưng trước tiên, việc ảnh hưởng đến giá trị đến biến sẽ cho phép gỡ lỗi nhanh hơn trong trường hợp có lỗi xảy ra trong lệnh gọi hàm đầu tiên và để tránh trùng lặp các tính toán đắt tiền.

MWE: (sử dụng (require 'ob-emacs-lisp)nếu cần)

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

Mở rộng khối mã thứ hai cho thấy:

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

Tôi đang thiếu gì?

(Điều này đã được thử nghiệm trên emacs 24.3.1, 24.4 và 24.5, sử dụng org 8.2.10)


Tôi nghĩ phải làm gì đó với Babel of Library.
yi.tang.uni

Câu trả lời:


7

Rõ ràng thêm mới #+name:trên #+results:khối.

Lưu ý: Cập nhật mã của bạn từ (message res)đến (message (format "%s" res))để ngăn chặn một Wrong type argument: stringp, 2025từ gây nhầm lẫn bổ sung.

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

Đã thử nghiệm bằng
GNU Emacs 24.4.1 (x86_64-unknown-cygwin, GTK + Phiên bản 3.10.9)
Phiên bản chế độ Org: 8.2.10


Ok, đó chắc chắn là giải pháp đơn giản nhất cho đến nay. Trong trường hợp này, thực sự không cần đến dòng #+name:trước #+call:, vì vậy nó không thêm bất kỳ sổ sách kế toán nào vào quy trình: chỉ cần đặt tên cho kết quả thay vì định nghĩa. Có thể nó không cảm thấy tự nhiên như nó có thể, nhưng ít nhất đó không phải là một công việc xung quanh để cầu xin một giải pháp thay thế.
T. Verron

Điều này thật tuyệt (+1). Tôi đã thử nó và nó hoạt động với org-mode 8.2.7c. Điều thú vị là việc tìm kiếm tài liệu thông tin của Chế độ Org để -resulttrả về không có kết quả. Vui lòng thêm một lưu ý rằng việc đặt tên cuộc gọi là bắt buộc và tên của kết quả phải là tên của cuộc gọi được thêm vào bởi -result. Ít nhất đó là những gì tôi lưu ý. (Nếu một người lỡ đặt tên cho cuộc gọi, lần đánh giá lại tiếp theo sẽ thêm một kết quả mới bỏ qua kết quả được đặt tên hiện có.
Tobias

@Tobias - Chỉ cần làm rõ, -resultchỉ là một quy ước đặt tên tôi đã sử dụng cho ví dụ này. Nếu bạn rõ ràng đang tìm kiếm kết quả của một khối nguồn thì hãy thêm ()vào tên khi chuyển tên dưới dạng một biến sang một khối khác hoặc bên trong một tham chiếu noweb.
Melioratus

1
Có vẻ như yêu cầu duy nhất là cái #+calltên được đặt tên. Tên của kết quả có thể được chọn tùy ý. Nếu cuộc gọi không được đặt tên, một dòng kết quả không tên bổ sung được tạo bởi cuộc gọi.
Tobias

Có phần nào trong hướng dẫn mô tả hành vi đó không?
Tobias

3

Bạn có thể sử dụng một :post-routine mà kết quả là :name. Gọi khối babel của bạn với thói quen bài này và đặt kết quả vào một ngăn kéo. Trong ví dụ sau đây thói quen bài này được đặt tên 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

Một cách khác để tránh tính toán lại các khối mã là :cacheđối số tiêu đề. Nếu điều này được đặt thành yeskhối mã và các đối số của nó được kiểm tra các thay đổi và nếu không có thay đổi nào thì kết quả trước đó được sử dụng mà không đánh giá lại khối mã nguồn.

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

Cảm ơn các hack! Có vẻ như cả hai giải pháp đều hoạt động, nhưng chúng tôi phần nào thoát khỏi "hãy thử nó, nó sẽ hoạt động theo cách bạn mong đợi" triết lý của org. Nếu nó không có giải pháp nào khác, tôi sẽ chấp nhận câu trả lời.
T. Verron

@ T.Verron Tôi nghĩ giải pháp thứ hai ( :cache yes) là giải pháp chuẩn. Nó cũng được mô tả trong hướng dẫn sử dụng org (xem phần 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` và cũng có lợi thế là nó tách hoàn toàn các khối mã. Ngay cả khi bạn chỉnh sửa khối mã thứ nhất và thử cái thứ hai là cái thứ nhất không được đánh giá. (Tùy thuộc vào nhiệm vụ có thể là lợi thế hoặc không hài lòng. Bạn chỉ cần ghi nhớ nó.)
Tobias

Tôi đã mệt mỏi đêm qua, tôi đã không nhận thấy ... Ngay cả khi không có lỗi khi đánh giá khối cuối cùng, liệu nó có thực sự hoạt động tốt hơn những gì tôi đã viết trong câu hỏi không? Rốt cuộc, vấn đề không phải là nó đánh giá lại cuộc gọi cho từng tham chiếu (nó cũng là một vấn đề, và sau đó, bộ đệm sẽ là giải pháp), nhưng tôi hoàn toàn không thể tham khảo nó.
T. Verron

@ T.Verron Kyle Meyer nói đúng. Các thay đổi orgmode.org/w/ không chưa thực hiện được. Phiên bản mới nhất có tại đây: orgmode.org/w/?p=org-mode.git;a=blob_plain;f=lisp/ Lỗi . Nhưng, có lẽ, có những thay đổi không tương thích ...
Tobias

@ T.Verron Ở trên tôi có nghĩa là "phát hành ổn định" chứ không phải "thân cây". Xin lỗi vì điều đó. Bạn có thể xem câu trả lời 1 của tôi là cách giải quyết cho tính năng bị thiếu.
Tobias

3

Tôi nghi ngờ bạn chỉ cần nâng cấp chế độ Org của bạn. Điều này hoạt động trên phần cuối của tôi (phiên bản phát triển hiện tại của Org) và nói chung sẽ hoạt động như thẻ release_8.3beta. Dưới đây là cam kết mà tôi nghĩ sẽ khắc phục vấn đề bạn đang mô tả.

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.

Ngoài việc tải Org từ repo git, một tùy chọn khác để chạy phiên bản mới hơn là cài đặt gói ELPA .


Chà, tôi có thể không sử dụng phiên bản phát triển, nhưng điều đó không có nghĩa là tôi chưa cập nhật kể từ năm 2013. Tôi không đến muộn. ;)Nói chính xác, của tôi org-versionlà 8.2.10. Tôi đã chỉnh sửa câu hỏi với thông tin này, nơi đáng lẽ phải ở vị trí đầu tiên.
T. Verron

Ooops, xin lỗi về thông tin sai lệch. Đó phải là cam kết, nhưng nó không có trong 8.2.10.
Kyle Meyer

Bạn có biết nơi tôi có thể tìm thấy một cuộc thảo luận về cam kết này?
T. Verron

Nếu một cuộc thảo luận về nó tồn tại, rất có thể nó sẽ nằm trong danh sách chế độ Org, nhưng tôi đã không tìm thấy bằng cách tìm kiếm và không có một tham chiếu nào trong thông điệp cam kết, vì vậy có thể không có.
Kyle Meyer
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.