Tôi có thể bao gồm một khối mã chung trong hai khối mã khác nhau trong chế độ Org không?


12

Tôi có một org-modetệp chứa một bảng dữ liệu và hai khối mã Python để trích xuất các bản tóm tắt khác nhau từ nó.

Tôi muốn chia sẻ một số hằng và hàm phổ biến giữa hai khối mã này. Lý tưởng nhất, tôi sẽ làm điều này bằng cách bao gồm mã chung vào một khối mã riêng, sẽ được tự động đưa vào và đánh giá bất cứ khi nào một trong hai khối còn lại được đánh giá. Trong cú pháp tạo thành, nó sẽ trông giống như sau:

#+NAME: init_block
#+BEGIN_SRC python
  ... common constants and functions here ...
#+END_SRC

#+NAME: summary_1
#+BEGIN_SRC python :prepend init_block
  ... data-processing code depending on init code goes here ...
#+END_SRC

#+NAME: summary_2
#+BEGIN_SRC python :prepend init_block
  ... more processing which also depends on init code ...
#+END_SRC

Tôi cho rằng tôi có thể sử dụng :sessiontùy chọn, nhưng tôi không muốn, vì hai lý do. Đầu tiên, nó thiết lập một hệ thống trạng thái, thay vì một hệ thống chạy từ đầu mỗi lần tôi sử dụng C-c C-ctrên một khối mã. Thứ hai, và có liên quan, bây giờ tôi phải nhớ đánh giá thủ công mã khởi tạo chung mỗi lần tôi mở tệp: Tôi không thể chỉ cập nhật bảng dữ liệu, đi đến một trong các khối tóm tắt và nhấn C-c C-cđể cập nhật nó.

Có một cách tốt để làm điều này?

Câu trả lời:


15

Bạn có thể thực hiện việc này một cách dễ dàng nhất bằng cách sử dụng cú pháp tham chiếu noweb của org-babel để lập trình biết chữ. Đây là một ví dụ:

* Initialization block containing function definition
#+NAME: init_block
#+BEGIN_SRC python
  constant=19
  def some_function(x):
    return constant * x
#+END_SRC

* Call the function on an integer
#+BEGIN_SRC python :noweb yes 
  <<init_block>>
  return some_function(13)
#+END_SRC

#+RESULTS:
: 247

* Call the function on a string
:PROPERTIES:
:noweb:    yes
:END:

#+BEGIN_SRC python
  <<init_block>>
  return some_function('abc')
#+END_SRC

#+RESULTS:
: abcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabc

Cảm ơn bạn. Điều này có vẻ tuyệt vời, tốt hơn nhiều so với giải pháp hackish của tôi. Tôi sẽ dùng thử trong vài ngày tới và xem tôi có vấn đề gì không.
Jon O.

@JonO. Nếu câu trả lời này có hiệu quả với bạn thì bạn vui lòng chấp nhận nó là chính xác - cảm ơn
không dùng nữa vào

4

Sau khi suy nghĩ thêm một chút, tôi tìm thấy một giải pháp cho vấn đề này. Nó sử dụng :session, nhưng ít nhất tôi có thể đảm bảo rằng mã khởi tạo chung luôn được chạy tự động trước khi đánh giá một trong các khối khác. 'Bí quyết' là sử dụng biến tiêu đề giả tham chiếu đến khối tiêu đề, khiến nó được đánh giá mỗi lần:

#+NAME: init_block
#+BEGIN_SRC python :session t
  constant=19
  def some_function(x):
    return constant * x
#+END_SRC

#+BEGIN_SRC python :session t :var dummy=init_block
some_function(13)
#+END_SRC

#+RESULTS:
: 247

Bây giờ tôi có thể thay đổi định nghĩa init_blockvà để chúng tự động được đánh giá lại bất cứ khi nào một khối khác đề cập đến nó sử dụng :var dummy=init_blockđược đánh giá. Điều này hoạt động tốt với điều kiện là các định nghĩa trong init_blocklà không có nghĩa và không trạng thái.

(Lưu ý rằng khi thay đổi khối Python thành :sessionchế độ, bạn phải xóa mọi returncâu lệnh cần thiết trong chế độ chức năng để trả về giá trị từ khối).

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.