ฉันสามารถรวมบล็อกรหัสทั่วไปในบล็อกโค้ดสองแบบในโหมดองค์กรได้หรือไม่


12

ฉันมีorg-modeไฟล์ที่มีสารบัญและบล็อกรหัส Python สองบล็อกเพื่อแยกข้อมูลสรุปที่แตกต่างออกไป

ฉันต้องการแบ่งปันค่าคงที่ทั่วไปและฟังก์ชั่นบางอย่างระหว่างโค้ดบล็อกทั้งสองนี้ โดยหลักการแล้วฉันจะทำเช่นนี้โดยแยกรหัสทั่วไปออกเป็นบล็อคโค้ดแยกซึ่งจะถูกรวมและประเมินโดยอัตโนมัติเมื่อใดก็ตามที่บล็อกสองบล็อกอื่นถูกประเมิน ในไวยากรณ์ที่สร้างขึ้นมันจะมีลักษณะดังนี้:

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

ฉันคิดว่าฉันสามารถใช้:sessionตัวเลือก แต่ฉันไม่ต้องการด้วยเหตุผลสองประการ ครั้งแรกมันตั้งค่าระบบ stateful มากกว่าหนึ่งซึ่งทำงานตั้งแต่เริ่มต้นทุกครั้งที่ฉันใช้C-c C-cในบล็อกรหัส ประการที่สองและที่เกี่ยวข้องตอนนี้ฉันต้องจำไว้ว่าต้องประเมินรหัสการเริ่มต้นทั่วไปด้วยตนเองทุกครั้งที่ฉันเปิดไฟล์: ฉันไม่สามารถอัปเดตตารางข้อมูลได้ให้ไปที่หนึ่งในบล็อกสรุปและกดC-c C-cเพื่ออัปเดต

มีวิธีที่ดีในการทำเช่นนี้?

คำตอบ:


15

คุณสามารถทำสิ่งนี้ได้ง่ายที่สุดโดยใช้ไวยากรณ์การอ้างอิง nowebของ bab-babel สำหรับการเขียนโปรแกรมความรู้ นี่คือตัวอย่าง:

* 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

ขอบคุณ. มันดูดีมากดีกว่าโซลูชันแฮ็คของฉัน ฉันจะลองใช้ในอีกไม่กี่วันข้างหน้าและดูว่าฉันมีปัญหาหรือไม่
Jon O.

@JonO หากคำตอบนี้เหมาะกับคุณคุณจะยอมรับได้ไหมว่าถูกต้องขอบคุณ
เลิกใช้แล้ว

4

หลังจากคิดเพิ่มอีกนิดฉันพบวิธีแก้ปัญหาบางส่วน มันใช้งาน:sessionได้ แต่อย่างน้อยฉันสามารถมั่นใจได้ว่ารหัสการเริ่มต้นทั่วไปจะทำงานโดยอัตโนมัติเสมอก่อนที่จะประเมินหนึ่งในบล็อกอื่น ๆ 'เคล็ดลับ' คือการใช้ตัวแปรส่วนหัวจำลองที่อ้างถึงบล็อกส่วนหัวทำให้ได้รับการประเมินในแต่ละครั้ง:

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

ตอนนี้ผมสามารถเปลี่ยนคำจำกัดความในinit_blockและมีพวกเขาโดยอัตโนมัติการประเมินอีกครั้งเมื่อใดก็ตามที่บล็อกซึ่งหมายถึงมันอีกโดยใช้:var dummy=init_blockการประเมิน สิ่งนี้ทำงานได้ดีหากคำจำกัดความinit_blockเป็น idempotent และไร้สัญชาติ

(โปรดทราบว่าเมื่อเปลี่ยนบล็อก Python เป็น:sessionโหมดคุณต้องลบreturnข้อความใด ๆที่จำเป็นในโหมดการทำงานเพื่อส่งคืนค่าจากบล็อก)

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.