原文Babel: Introduction, 由 Eric Schulte , Dan Davison, Tom Dye 編輯结窘,維護。本文只做學習之用充蓝。本文章同時發(fā)表在自己的私人博客里隧枫,歡迎前往閱讀。
序言<a id="introduction"></a>
Bable 可讓許多不同的語言工作一起谓苟。 編程語言生活在自然語言的 Org-mode
文檔的代碼塊之中官脓。 一個數(shù)據(jù)片段可從一個表格傳遞給一個 Pythoh
代碼塊,然后可能再轉(zhuǎn)移到一個 R
代碼塊涝焙, 最終以數(shù)據(jù)塊被嵌入段落的中間而終結(jié)卑笨,或者通過 gnuplot
代碼塊生成圖片嵌入在文檔中。
通過擴展 Org-mode, 使其具有編輯,導出和執(zhí)行源代碼的功能, Babel 將 Org-mode
變成了文學編程和可重復性研究的工具仑撞。
Babel 通過提供以下特性來增強 Org-mode對代碼代碼塊的支持: Babel augments Org-mode support for code blocks by providing:
- 代碼塊的交互和執(zhí)行結(jié)果導出
- 代碼塊可像函數(shù)一樣可參數(shù)化赤兴,引用其他代碼塊,可被遠程調(diào)用
- 拼接隧哮,導出源代碼到文件支持文學編程桶良。
概述<a id="sec-2"></a>
Babel 在幾個不同的方面提供了新的功能,不同的人可能想在不同的地方開始沮翔。
-
在
Org-mode
中使用代碼塊: 如果目前你還不知道怎么在Org-mode
中創(chuàng)建代碼塊陨帆, 或者不清楚怎樣在Org-mode
的緩沖區(qū)和語言主模式編輯緩沖區(qū)(the language major-mode edit buffer)之間切換, 那么你需要應(yīng)該看看Org 手冊中的相關(guān)部分 和 下面的代碼塊章節(jié), 嘗試下采蚀,然后趕緊回來疲牵。 -
執(zhí)行代碼: Babel 的核心是能夠在
Org-mode
代碼塊中執(zhí)行代碼, 從其他塊和表格獲取輸入榆鼠,并輸出到更多的塊和表纲爸。 從源代碼執(zhí)行開始描述。 -
Literate Programming: 程序員編寫的代碼妆够,通常以其他方式執(zhí)行(例如從命令行或?qū)⑵湟氲浇换ナ綍捴校?那么對 Babel 的簡單介紹就是將代碼放在
Org-mode
文件的代碼塊中识啦, 然后使用 Babel 的Literate Programming
支持從Org-mode
文件中擴展提取源代碼。
所有這些用例以及 Babel 功能的詳盡文檔都被涵蓋在 Org 手冊的 使用源代碼中责静。
初始配置<a id="getting-started"></a>
If you have a working Emacs installation, then getting started with Babel is a simple process.
If you are running Emacs24 a current version of Org-mode with Babel is already available by default. Otherwise, it is strongly recommended that you update to the latest version of Org-mode by keeping current with Org-mode development. As of Org-mode 7.0, Babel is included as part of Org-mode.
Optionally activate the subset of languages that you will want to execute with Babel. See Configure active languages instructions. Emacs Lisp is activated by default so this step can be skipped for now and all
emacs-lisp
examples will still work as expected.If you have made any changes don’t forget to evaluate your modified .emacs.
代碼塊<a id="source-code-blocks"></a>
代碼塊在 Org-mode
中<a id="source-code-blocks-org"></a>
Babel 是關(guān)于 Org-mode
中代碼塊的袁滥。 如果還不熟悉 Org-mode
中的代碼塊的概念盖桥,請在繼續(xù)之前查看 Org-mode手冊的相關(guān)章節(jié)灾螃。
受到支持語言的代碼塊可以出現(xiàn)在 Org-mode
文件的任意位置。 代碼塊可以直接在 Org-mode
文件中編輯揩徊,但通過 C-c '
調(diào)用的函數(shù) org-edit-src-code
編輯代碼往往更容易腰鬼。 將代碼塊放全新的緩沖區(qū)中嵌赠,同時激活相應(yīng)語言的模式,語言的編輯特性你全都可用,真是爽熄赡。
#+begin_src language org-switches
,body
#+end_src
ruby
代碼的代碼塊如下所示:
#+begin_src ruby
,require 'date'
,"This file was last evaluated on #{Date.today}"
#+end_src
代碼塊在 Babel
中<a id="source-code-blocks-babel"></a>
Babel 向代碼塊添加了一些新的元素姜挺。 基本結(jié)構(gòu)變成了:
#+begin_src language org-switches header-arguments
,body
#+end_src
-
language: 代碼塊中代碼的語言標示。 有效值必須是
org-babel-interpreters
的成員彼硫。 -
header-arguments:
header-arguments
控制源代碼塊的執(zhí)行和輸出的許多方面炊豪。
請參閱Header Arguments部分,以查看可用的 header-arguments=
拧篮。
-
body: 等待被執(zhí)行的源代碼词渤。 一個重要的鍵綁定
C-c '
, 調(diào)用org-edit-src-code
,打開一個包含適合于該語言major mode
的編輯緩沖區(qū)串绩。
然后你就可以像往常在emacs編輯代碼那樣來編輯你的代碼塊缺虐。
源代碼執(zhí)行<a id="source-code-execution"></a>
Babel 通過將代碼傳遞給解釋器來執(zhí)行解釋語言(如shell,python礁凡,R等)的代碼塊高氮。 在執(zhí)行結(jié)果上可以做進一步的操作,如果你想的話顷牌。
示例<a id="sec-5-1"></a>
以下是三種不同語言的代碼塊剪芍,其后是其輸出。 如果正在Emacs中查看本文檔的 Org-mode
版本韧掩,則把光標放置在塊的任何位置紊浩,然后按 C-c C-c
執(zhí)行代碼(并隨意更改它)。
Ruby<a id="sec-5-1-1"></a>
在 Org-mode
的文件中:
#+begin_src ruby
require 'date'
"This file was last evaluated on #{Date.today}"
#+end_src
HTML 導出的代碼:
require 'date'
"This file was last evaluated on #{Date.today}"
HTML 導出的執(zhí)行結(jié)果:
This file was last evaluated on 2017-04-05
Shell<a id="sec-5-1-2"></a>
在 Org-mode
的文件中:
#+begin_src sh
echo "This file takes up `du -h babel-intro.org |sed 's/\([0-9k]*\)[ ]*babel-intro.org/\1/'`"
#+end_src
HTML 導出的代碼:
echo "This file takes up `du -h babel-intro.org |sed 's/\([0-9k]*\)[ ]*babel-intro.org/\1/'`"
HTML 導出的執(zhí)行結(jié)構(gòu):
This file takes up 36K
R<a id="sec-5-1-3"></a>
當前這個文件中最常用的詞是疗锐? 在 Org-mode
文件中:
#+begin_src R :colnames yes
words <- tolower(scan("babel-intro.org", what="", na.strings=c("|",":")))
t(sort(table(words[nchar(words) > 3]), decreasing=TRUE)[1:10])
#+end_src
HTML 導出的代碼:
words <- tolower(scan("babel-intro.org", what="", na.strings=c("|",":")))
t(sort(table(words[nchar(words) > 3]), decreasing=TRUE)[1:10])
ditaa<a id="sec-5-1-4"></a>
在 Org-mode
文件中:
#+begin_src ditaa :file blue.png :cmdline -r
+---------+
| cBLU |
| |
| +----+
| |cPNK|
| | |
+----+----+
#+end_src
HTML導出的代碼: HTML導出的結(jié)果圖:
![](http://orgmode.org/worg/images/babel/blue.png)
捕獲代碼執(zhí)行結(jié)果<a id="results"></a>
Babel 提供了兩種根本不同的模式來捕獲代碼執(zhí)行的結(jié)果: functional mode 和 scripting mode 坊谁。 模式的選擇可以通過配置 :results
頭參數(shù)來指定。
:results value
(functional mode)<a id="results-value"></a>
代碼執(zhí)行的結(jié)果是代碼塊中最后一個語句的值滑臊。 在 functional mode 下口芍,代碼塊是具有返回值的函數(shù)。 一個代碼塊的返回值可以用作另一代碼塊的輸入雇卷,即使是不同語言的輸入鬓椭。 這樣的話,Babel成為一種元編程語言关划。 如果塊返回表格數(shù)據(jù)(某種類型的向量小染,數(shù)組或表),那么將可以作為 Org-mode
的表格保存在緩沖區(qū)中贮折。 functional mode 是默認設(shè)置裤翩。
作為示例,觀察以下python代碼塊及其輸出调榄。
import time
print("Hello, today's date is %s" % time.ctime())
print("Two plus two is")
return 2 + 2
請注意踊赠,在 functional mode 下呵扛,輸出只由最后一個語句返回,沒有其他情況筐带。
:results output
(scripting mode)<a id="results-output"></a>
在 scripting mode 中今穿,Babel捕獲代碼塊的文本輸出并將其放置在 Org-mode
的緩沖區(qū)中。 它被稱為 scripting mode 伦籍,因為代碼塊包含一系列命令蓝晒,并返回每個命令的輸出。 與功能模式不同帖鸦,代碼塊本身除了其包含的命令的輸出之外沒有返回值拔创。<a id="fnr.2" class="footref" href="#fn.2">2</a>
觀察以下使用 scripting mode 執(zhí)行代碼塊的結(jié)果。
import time
print("Hello, today's date is %s" % time.ctime())
print('Two plus two is')
2 + 2
在這里富蓄, scripting mode 返回了python寫到 stdout
的文本剩燥。 因為代碼塊不包含最后一個語句 (2 + 2)
的 print()
語句,所以結(jié)果中不會出現(xiàn)4立倍。
基于會話的代碼塊<a id="sec-5-3"></a>
對于某些語言灭红,例如Python,R口注,ruby和shell变擒,可以在Emacs中運行一個不完備的交互式會話進程。 這意味著創(chuàng)建了一個不同源代碼塊之間共享數(shù)據(jù)對象的持久化環(huán)境寝志。 Babel 支持使用 :session
頭參數(shù)來 指定代碼塊運行于特定會話中娇斑。 如果頭參數(shù)被賦予一個值,那么該參數(shù)將被用作會話的名稱材部。 因此毫缆,可以并發(fā)的在不同的會話中運行同一語言的不同代碼塊。
基于特定會話的代碼塊對于原型設(shè)計和調(diào)試特別有用乐导。 函數(shù) org-babel-pop-to-session
可用于切換會話緩沖區(qū)苦丁。
一旦代碼塊編輯完成,通常最好在會話之外執(zhí)行它物臂,因為這樣它執(zhí)行的環(huán)境將是確定的旺拉。
With R, the session will be under the control of Emacs Speaks Statistics as usual, and the full power of ESS is thus still available, both in the R session, and when switching to the R code edit buffer with
?C-c '?
.
代碼塊的入?yún)?lt;a id="arguments-to-source-code-blocks"></a>
Babel 支持代碼塊的參數(shù)化,即可以將參數(shù)傳遞給代碼塊棵磷,從而使它們函數(shù)化蛾狗。 functional mode 和 scripting mode 都支持入?yún)ⅰ?/p>
代碼塊作為函數(shù)的簡單示例<a id="using-a-code-block-as-a-function"></a>
首先我們來看一個非常簡單的例子。 以下源代碼塊使用Python定義了一個函數(shù)仪媒,求入?yún)⒌钠椒健?/p>
return x*x
在 Org-mode 文件中, 函數(shù)定義如下:
#+name: square
#+header: :var x=0
#+begin_src python
return x*x
#+end_src
調(diào)用函數(shù)如下:
#+call: square(x=6,y=8)
(對于 call
語法細節(jié)請參閱 Library of Babel)
36
Org-mode
表格作為入?yún)⒌母鼜碗s的示例<a id="sec-5-4-2"></a>
在本例中沉桌,使用Emacs Lisp定義的一個名為 fibonacci-seq
的函數(shù)。 函數(shù) fibonacci-seq
計算斐波納契序列。 該函數(shù)只需要一個參數(shù)蒲牧,在當前情況下參數(shù)即為 Org-mode
表格的引用。
下面即為傳遞給 fibonacci-seq
的 Org-mode
表格:
| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
| 2 | 4 | 6 | 8 | 10 | 12 | 14 | 16 | 18 | 20 |
表格在 Org-mode
的緩沖區(qū)中如下所示:
#+tblname: fibonacci-inputs
| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
| 2 | 4 | 6 | 8 | 10 | 12 | 14 | 16 | 18 | 20 |
Emacs Lisp的源代碼:
(defun fibonacci (n)
(if (or (= n 0) (= n 1))
n
(+ (fibonacci (- n 1)) (fibonacci (- n 2)))))
(mapcar (lambda (row)
(mapcar #'fibonacci row)) fib-inputs)
在 Org-mode
中函數(shù)如下所示:
#+name: fibonacci-seq
#+begin_src emacs-lisp :var fib-inputs=fibonacci-inputs
(defun fibonacci (n)
(if (or (= n 0) (= n 1))
n
(+ (fibonacci (- n 1)) (fibonacci (- n 2)))))
(mapcar (lambda (row)
(mapcar #'fibonacci row)) fib-inputs)
#+end_src
fibonacci-seq
的返回值赌莺,也是一個表格:
內(nèi)聯(lián)(In-line)的代碼塊<a id="sec-5-5"></a>
可使用以下語法內(nèi)聯(lián)(In-line)的執(zhí)行代碼:
Without header args: src_lang{code} or with header args: src_lang[args]{code},
for example src_python[:session]{10*x}, where x is a variable existing in the
python session.
代碼如下:
src_python{return "Hello World!"}
執(zhí)行結(jié)果: Hello World!
代碼塊擴展<a id="sec-5-6"></a>
Babel 在執(zhí)行之前“擴展”代碼塊冰抢,即,執(zhí)行代碼包括把引用的數(shù)據(jù)(或代碼)填充到代碼塊內(nèi)容里艘狭。 可以預覽展開的內(nèi)容挎扰,還可以在 tangling 期間展開代碼。 擴展時巢音,頭參數(shù)和變量需要一并考慮進去遵倦。
preview:
C-c M-b p
(C-c C-v v
) 關(guān)聯(lián)到org-babel-expand-src-block
函數(shù)。它可用于在代碼塊中預覽擴展的內(nèi)容, 對調(diào)試很有用官撼。-
tangling: 擴展的的代碼塊可以被 tangled 梧躺。 tangling 可能包括的變量值
- 其他代碼的執(zhí)行結(jié)果,
- 存儲在標題屬性中變量傲绣,或者
- 表格掠哥。
tangling 擴展代碼塊的一個可能用途是用于emacs初始化。 用戶名和密碼等值可以存儲在標題屬性或表格中秃诵。 可以使用 :no-expand
頭參數(shù)來阻止 tangling 期間代碼塊的擴展续搀。
下面是代碼塊及其生成的擴展的示例。
數(shù)據(jù)被存儲在表格中:
| username | john-doe |
| password | abc123 |
引用數(shù)據(jù)表格的代碼塊:
(setq my-special-username (first (first data)))
(setq my-special-password (first (second data)))
在代碼塊內(nèi)部菠净, C-c M-b p
(C-c C-v v
)擴展內(nèi)容如下:
(let ((data (quote (("john-doe") ("abc123")))))
(setq my-special-username (first (first data)))
(setq my-special-password (first (second data))))
Org-mode
的元編程語言<a id="meta-programming-language"></a>
因為用一種語言編寫的函數(shù)的返回值可以被傳遞給另一種語言編寫的函數(shù)禁舷, 或者傳遞到本身就可程序化的 Org-mode
的表格中, 所以可將 Babel 用作元功能編程語言毅往。 Bable 可使許多語言一起工作, 混合使用各語言牵咙,每種語言可用于最合適的任務(wù)。
例如攀唯,在shell中進行一些系統(tǒng)診斷霜大,并用R圖形化診斷結(jié)果.
-
使用shell代碼創(chuàng)建一個代碼塊,列出program目錄中的目錄以及它們的大小革答。Babel自動將輸出轉(zhuǎn)換為
Org-mode
表格战坤。#+name: directories #+begin_src sh :results replace cd ~/program/ && du -sc * | grep -v total #+end_src
代碼如下:
cd ~/program/ && du -sc * | grep -v total
結(jié)果如下:
#+RESULTS: directories | 2392 | github | | 90728 | org | | 15820 | program | | 190488 | program.tgz |
-
一行R語言編寫的函數(shù)將
Org-mode
表中的數(shù)據(jù)繪制為餅形圖。請注意残拐,當前代碼塊如何使用前一代碼塊的途茫。srcname
來獲取的數(shù)據(jù)在
Org-mode
文件中:#+name: directory-pie-chart(dirs = directories) #+begin_src R :session R-pie-example :file ../images/babel/dirs.png :var dirs=directories() :results graphics pie(dirs[,1], labels = dirs[,2]) #+end_src
注:
:results graphics
請參閱 Org Mode Features for R Source Code BlocksHTML 導出的代碼:
pie(dirs[,1],labels=dirs[,2])
在Org表格中使用代碼塊<a id="spreadsheet"></a>
除了可將表格中的數(shù)據(jù)作為參數(shù)傳遞給代碼塊和結(jié)果存儲為表格外, Babel 還有第三種方式使用 Org-mode
表格溪食。 Org-mode
現(xiàn)有電子表格 功能允許使用 #+TBLFM
從指定單元格值自動計算出其他單元格值囊卜。 通過以上方式,表可使用calc 和 emacs lisp來執(zhí)行計算任務(wù)。
Babel 有效擴展了 #+TBLFM
行使用代碼塊(以任何語言)進行必要計算的能力栅组。
示例<a id="sec-6-1"></a>
示例 1: 使用R生成數(shù)據(jù)概要<a id="sec-6-1-1"></a>
將使用幾個數(shù)字的平均值來填充 Org-mode
表中的一個單元格雀瓢,來做簡單示例。 首先玉掸,要生成數(shù)據(jù), 以下代碼塊生成0和1之間的五個隨機數(shù)來填充了 Org-mode
表刃麸。
在 Org-mode
文件中,如下所示:
#+name: tbl-example-data
#+begin_src R
runif(n=5, min=0, max=1)
#+end_src
HTML 導出的代碼如下:
runif(n=5, min=0, max=1)
緊接著定義一個代碼塊計算來表列的平均值。
在 Org-mode
文件中,如下所示:
#+name: R-mean
#+begin_src R :var x=""
colMeans(x)
#+end_src
HTML 導出的代碼如下:
colMeans(x)
最后司浪,創(chuàng)建使用R代碼的表泊业。 通過使用 org-sbe
(’source block evaluate’)宏來完成的代碼塊的調(diào)用。
在 Org-mode
文件中啊易,表格調(diào)用代碼塊如下所示:
#+tblname: summaries
| mean |
|-------------------|
| 0.779619386699051 |
#+TBLFM: @2$1='(org-sbe "R-mean" (x "tbl-example-data()"))
HTML export of code:
mean |
---|
0.58 |
重新計算表格公式吁伺,請在表格中使用 C-u C-c C-c
。 每次重新計算表格公式時租谈,代碼塊都會再次計算篮奄,因此計算的平均值會發(fā)生變化。
示例 2: Babel 的測試套件<a id="sec-6-1-2"></a>
While developing Babel, we used a suite of tests implemented as a large Org-mode table.
在開發(fā) Babel 時割去,開發(fā)者曾使用了一個居大的 Org-mode
表作為測試套件宦搬。 要運行測試套件,我們只需使用 C-u C-c C-c
對表進行計算:運行所有測試劫拗,將結(jié)果與期望進行比較间校,并使用結(jié)果和通過/失敗的狀態(tài)信息來更新表。
測試套件的簡單版本如下.
在 Org-mode
文件中页慷,如下所示:
#+TBLNAME: org-babel-tests
| functionality | block | arg | expected | results | pass |
|------------------+--------------+-----+-------------+-------------+------|
| basic evaluation | | | | | pass |
|------------------+--------------+-----+-------------+-------------+------|
| emacs lisp | basic-elisp | 2 | 4 | 4 | pass |
| shell | basic-shell | | 6 | 6 | pass |
| ruby | basic-ruby | | org-babel | org-babel | pass |
| python | basic-python | | hello world | hello world | pass |
| R | basic-R | | 13 | 13 | pass |
#+TBLFM: $5='(if (= (length $3) 1) (org-sbe $2 (n $3)) (org-sbe $2)) :: $6='(if (string= $4 $5) "pass" (format "expected %S but was %S" $4 $5))
HTML 導出的代碼:
functionality | block | arg | expected | results | pass |
---|---|---|---|---|---|
basic evaluation | pass | ||||
emacs lisp | basic-elisp | 2 | 4 | 4 | pass |
shell | basic-shell | 6 | 6 | pass | |
ruby | basic-ruby | org-babel | org-babel | pass | |
python | basic-python | hello world | hello world | pass | |
R | basic-R | 13 | 13 | pass |
-
用于測試的代碼塊
Org-mode
文件中憔足,如下所示::#+name: basic-elisp #+begin_src emacs-lisp :var n=0 (* 2 n) #+end_src
HTML 導出代碼,如下所示::
(* 2 n)
Org-mode
文件中酒繁,如下所示::#+name: basic-shell #+begin_src sh :results silent expr 1 + 5 #+end_src
HTML 導出代碼滓彰,如下所示::
expr 1 + 5
Org-mode
文件中,如下所示::#+name: date-simple #+begin_src sh :results silent date #+end_src
HTML 導出代碼州袒,如下所示::
date
Org-mode
文件中揭绑,如下所示::#+name: basic-ruby #+begin_src ruby :results silent "org-babel" #+end_src
HTML 導出代碼,如下所示::
"org-babel"
Org-mode
文件中郎哭,如下所示:#+name: basic-python #+begin_src python :results silent "hello world" #+end_src
HTML 導出代碼他匪,如下所示::
return "hello world"
Org-mode
文件中,如下所示::#+name: basic-R #+begin_src R :results silent b <- 9 b + 4 #+end_src
HTML 導出代碼夸研,如下所示::
b <- 9 b + 4
Babel庫文件<a id="library-of-babel"></a>
(可參閱 Org manual:Library-of-Babel)
正如上面的 square 示例中看到的邦蜜,一旦代碼塊被定義,可使用 lob
符號反復調(diào)用:
#+lob: square(x=6)
但是亥至,若是需要為每個 Org-mode
緩沖區(qū)提供的通用,可重用的代碼塊呢悼沈?
除了當前的緩沖區(qū)外贱迟, Babel 還會搜索 *Babel*庫文件中預先定義的代碼塊。 這是一個用戶可擴展的現(xiàn)成的代碼塊集合絮供,用于處理常見任務(wù)衣吠。 對于 Bable 庫(尚未完成!)的一個可能的用途就是是使用R壤靶,gnuplot缚俏,asymptote等語言為 Org-mode
表中保存的數(shù)據(jù)提供繪圖功能。 如果你定義的某些代碼塊 對其他 Org-mode
用戶也非常有用萍肆,可考慮將其添加到 Babel 庫中; 類似的,可以隨時求助胀屿,*Babel* 可引用外部代碼來解決問題 – 其他Babel用戶也有機會提供一些有用的代碼塘揣。
Babel預先填充(即把庫中的代碼塊加載到緩沖區(qū)中)位于 Babel庫文件 中的代碼塊 - library-of-babel.org 上的原始文件。 可使用 org-babel-lob-ingest
(綁定到 C-c C-v i
)從任何 Org-mode
文件中向庫添加代碼塊宿崭。
(org-babel-lob-ingest "path/to/file.org")
注: 可以將表值或源代碼塊的輸出傳遞給 Babel 庫函數(shù)亲铡。 還可以在代碼塊的參數(shù)中引用 Babel 函數(shù)庫函數(shù)。
文學化編程<a id="literate-programming"></a>
Let us change our traditional attitude to the construction of programs: Instead of imagining that our main task is to instruct a computer what to do, let us concentrate rather on explaining to human beings what we want a computer to do.
讓我們改改傳統(tǒng)上構(gòu)建程序的態(tài)度:不要認為程序的主要任務(wù)是指導計算機怎么做葡兑,相反奖蔓,程序要致力于向人們解釋,它想讓計算機做什么讹堤。<a id="fnr.3" class="footref" href="#fn.3">3</a>
The practitioner of literate programming can be regarded as an essayist, whose main concern is with exposition and excellence of style. Such an author, with thesaurus in hand, chooses the names of variables carefully and explains what each variable means. He or she strives for a program that is comprehensible because its concepts have been introduced in an order that is best for human understanding, using a mixture of formal and informal methods that reinforce each other.
文學編程人士可被視為作家吆鹤,他們首要考慮的任務(wù)是如何清楚地闡述、如何形成優(yōu)秀的風格洲守。 這樣的作者胸有成竹疑务,會仔細地挑選變量名,并給予解釋梗醇。為力求程序之可讀知允, 他/她使用形式和非形式互補的混合手法,將各種概念按照人們能理解的方式順序編排下來叙谨。<a id="fnr.3.100" class="footref" href="#fn.3">3</a> – Donald Knuth
Babel支持 文學編程 (LP)温鸽,允許編程行為發(fā)生在 Org-mode
文檔中。 然后可將 Org-mode
文件導出(用LP語言編寫)到HTML或LaTeX等更可視化的文本格式中以供人類查閱和使用手负, 并且可以將嵌入的源代碼( tangle in LP speak)轉(zhuǎn)換成源代碼文件以供計算機執(zhí)行涤垫。
為了支持這些操作, Babel 依賴于 Org-mode
的 文檔的導出功能 來編排文檔竟终, 依賴于使用 Noweb reference syntax tangling 代碼文件的 org-babel-tangle
( C-c C-v t
) 函數(shù)雹姊。
以下示例演示了在 Babel 中 tangling 的過程。
tangling 的示例<a id="sec-8-1"></a>
簡單文學編程示例 (Noweb syntax)<a id="literate-programming-example"></a>
Tangling functionality is controlled by the
tangle
family of tangle header arguments. These arguments can be used to turn tangling on or off (the default), either for the code block or the Org-mode heading level.
以下代碼塊演示如何使用 org-babel-tangle
( C-c C-v t
) 把分散的代碼塊 tangle 為單個源代碼文件衡楞。
以下兩個代碼塊沒有 tangle
頭參數(shù)吱雏,因此不會創(chuàng)建源代碼文件敦姻。 它們通過第三個代碼塊被包含在源代碼文件中,該代碼塊具有 tangle
頭參數(shù)歧杏。
Org-mode
文件中镰惦,如下所示::
#+name: hello-world-prefix
#+begin_src sh :exports none
echo "/-----------------------------------------------------------\\"
#+end_src
Org-mode
文件中,如下所示:
#+name: hello-world-postfix
#+begin_src sh :exports none
echo "\-----------------------------------------------------------/"
#+end_src
第三個代碼塊具有 tangle
頭參數(shù)犬绒,指出將被寫入的源代碼的文件的名稱旺入。 它還包含了前面兩個代碼塊的Noweb樣式引用。 這些引用將在 tangling 期間擴展凯力,以使它們包含在輸出文件中岖寞。
Org-mode
文件中,如下所示::
#+name: hello-world
#+begin_src sh :tangle hello.sh :exports none :noweb yes
<<hello-world-prefix>>
echo "| hello world |"
<<hello-world-postfix>>
#+end_src
調(diào)用函數(shù) org-babel-tangle
( C-c C-v t
)將shell源碼寫到 hello.sh
文件中:
#!/usr/bin/env sh
echo "/-----------------------------------------------------------\\"
echo "| hello world |"
echo "\-----------------------------------------------------------/"
此外库物,可以使用以下語法來插入代碼塊執(zhí)行的結(jié)果侨核,在下面情況下是名為 example-block
的代碼塊的執(zhí)行結(jié)果。
<< example-block() >>
任何可選參數(shù)都可以傳遞給 example-block()
祈惶,方法是將參數(shù)放入括號內(nèi)雕旨,并遵循調(diào)用代碼塊函數(shù)定義的約定(參見 babel庫)。 如下:
<< example-block(a=9) >>
參數(shù) “a” 的值設(shè)置為等于 “9”捧请。 請注意凡涩,這些參數(shù)不在當前源代碼塊中執(zhí)行,而是按字面順序傳遞給 example-block()
疹蛉。
用Bable初始化Emacs<a id="emacs-initialization"></a>
![](http://orgmode.org/worg/images/babel/dot-emacs.png)
Babel 對于將Emacs初始化信息嵌入 Org-mode
文件中有特別的支持活箕。 org-babel-load-file
函數(shù)可用于加載嵌入在 Org-mode
文件中的Emacs Lisp代碼塊,方法與加載常規(guī)Emacs Lisp文件(如.emacs)相同可款。
這就允許利用Org-mode的功能特性讹蘑,例如折疊,標簽筑舅,筆記座慰,HTML導出等,來組織和維護Emacs初始化配置翠拣。
要想了解這一點版仔,可以參考簡單的優(yōu)雅的Emacs初始化示例,或者查看 Org-babel-emacs-starter-kit 中提供的 Phil Hagelberg 的優(yōu)秀 emacs-starter-kit 的 Babel Literate Programming 版本误墓。 To try this out, either see the simple Literate Emacs Initialization example, or check out the Babel Literate Programming version of Phil Hagelberg’s excellent emacs-starter-kit available at Org-babel-emacs-starter-kit.
-
優(yōu)雅的Emacs初始化
請按照以下5個步驟進行操作:
-
在主目錄的內(nèi)創(chuàng)建一個名為
.emacs.d
的目錄;mkdir ~/.emacs.d
-
checkout 最新版本的
Org-mode
到這個新目錄的src子目錄中; of this new directory;cd ~/.emacs.d mkdir src cd src git clone git://orgmode.org/org-mode.git
-
將以下代碼塊放入Emacs初始化目錄(
~/.emacs.d
)下名為init.el
的文件中蛮粮。;;; init.el --- Where all the magic begins ;; ;; This file loads Org-mode and then loads the rest of our Emacs initialization from Emacs lisp ;; embedded in literate Org-mode files. ;; Load up Org Mode and (now included) Org Babel for elisp embedded in Org Mode files (setq dotfiles-dir (file-name-directory (or (buffer-file-name) load-file-name))) (let* ((org-dir (expand-file-name "lisp" (expand-file-name "org" (expand-file-name "src" dotfiles-dir)))) (org-contrib-dir (expand-file-name "lisp" (expand-file-name "contrib" (expand-file-name ".." org-dir)))) (load-path (append (list org-dir org-contrib-dir) (or load-path nil)))) ;; load up Org-mode and Org-babel (require 'org-install) (require 'ob-tangle)) ;; load up all literate org-mode files in this directory (mapc #'org-babel-load-file (directory-files dotfiles-dir t "\\.org$")) ;;; init.el ends here
在Emacs Lisp代碼塊中實現(xiàn)所有Emacs定制,嵌入在該目錄中的
Org-mode
文件中; 和重啟Emacs讀取自定義配置谜慌。
-
可重復性研究<a id="reproducable-research"></a>
An article about computational science in a scientific publication is not the scholarship itself, it is merely advertising of the scholarship. The actual scholarship is the complete software development environment and the complete set of instructions which generated the figures.
– D. Donoho
可重復性研究 (RR)是與科研出版物一起分發(fā)的所有數(shù)據(jù)然想,軟件源代碼和重現(xiàn)出版物中討論的結(jié)果所需的工具的方法。 因此欣范,RR包不僅描述了研究及其結(jié)果变泄,而且成為可以復制和擴展研究的完整實驗室令哟。
Org-mode
已經(jīng)很好的支持導出到HTML和LaTeX。 Babel 通過激活嵌入在 Org-mode
文檔中的數(shù)據(jù)和代碼塊妨蛹,使組織模式成為RR的工具; 整個文檔變得可執(zhí)行屏富。 這使得鼓勵讀者重新創(chuàng)建結(jié)果并實驗自己的思路來分發(fā)科研成果成為可能。
Sweave 是目前比較知名的RR工具蛙卤,它提供了將R代碼嵌入到LaTeX文檔中的機制狠半。 Sweave是一個成熟而且非常有用的工具,但我們認為 Babel 有幾個優(yōu)點:
- 支持多種語言
- 導出過程靈活強大颤难,除了LaTeX之外神年,還包括HTML作為目標格式; 和
- 文檔可利用
Org-mode
強大的功能特性,支持項目規(guī)劃和任務(wù)管理等行嗤。