Emacs讓編程多一種可能

原文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í)行源代碼的功能, BabelOrg-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 文件的代碼塊中识啦, 然后使用 BabelLiterate 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.

  1. 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.

  2. 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.

  3. 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é)果圖:

捕獲代碼執(zhí)行結(jié)果<a id="results"></a>

Babel 提供了兩種根本不同的模式來捕獲代碼執(zhí)行的結(jié)果: functional modescripting 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 modescripting 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-seqOrg-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é)果.

  1. 使用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 |
    
  2. 一行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 Blocks

    HTML 導出的代碼:

    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
  1. 用于測試的代碼塊

    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-tangleC-c C-v t ) 函數(shù)雹姊。

以下示例演示了在 Babeltangling 的過程。

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

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-kitBabel 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.

  1. 優(yōu)雅的Emacs初始化

    請按照以下5個步驟進行操作:

    1. 在主目錄的內(nèi)創(chuàng)建一個名為 .emacs.d 的目錄;

      mkdir ~/.emacs.d
      
    2. checkout 最新版本的 Org-mode 到這個新目錄的src子目錄中; of this new directory;

      cd ~/.emacs.d
      mkdir src
      cd src
      git clone git://orgmode.org/org-mode.git
      
    3. 將以下代碼塊放入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
      
    4. 在Emacs Lisp代碼塊中實現(xiàn)所有Emacs定制,嵌入在該目錄中的 Org-mode 文件中; 和

    5. 重啟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和LaTeXBabel 通過激活嵌入在 Org-mode 文檔中的數(shù)據(jù)和代碼塊妨蛹,使組織模式成為RR的工具; 整個文檔變得可執(zhí)行屏富。 這使得鼓勵讀者重新創(chuàng)建結(jié)果并實驗自己的思路來分發(fā)科研成果成為可能。

Sweave 是目前比較知名的RR工具蛙卤,它提供了將R代碼嵌入到LaTeX文檔中的機制狠半。 Sweave是一個成熟而且非常有用的工具,但我們認為 Babel 有幾個優(yōu)點:

  • 支持多種語言
  • 導出過程靈活強大颤难,除了LaTeX之外神年,還包括HTML作為目標格式; 和
  • 文檔可利用 Org-mode 強大的功能特性,支持項目規(guī)劃和任務(wù)管理等行嗤。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末已日,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子昂验,更是在濱河造成了極大的恐慌捂敌,老刑警劉巖艾扮,帶你破解...
    沈念sama閱讀 212,542評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件既琴,死亡現(xiàn)場離奇詭異,居然都是意外死亡泡嘴,警方通過查閱死者的電腦和手機甫恩,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,596評論 3 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來酌予,“玉大人磺箕,你說我怎么就攤上這事∨壮妫” “怎么了松靡?”我有些...
    開封第一講書人閱讀 158,021評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長建椰。 經(jīng)常有香客問我雕欺,道長,這世上最難降的妖魔是什么棉姐? 我笑而不...
    開封第一講書人閱讀 56,682評論 1 284
  • 正文 為了忘掉前任屠列,我火速辦了婚禮,結(jié)果婚禮上伞矩,老公的妹妹穿的比我還像新娘笛洛。我一直安慰自己,他們只是感情好乃坤,可當我...
    茶點故事閱讀 65,792評論 6 386
  • 文/花漫 我一把揭開白布苛让。 她就那樣靜靜地躺著沟蔑,像睡著了一般。 火紅的嫁衣襯著肌膚如雪蝌诡。 梳的紋絲不亂的頭發(fā)上溉贿,一...
    開封第一講書人閱讀 49,985評論 1 291
  • 那天,我揣著相機與錄音浦旱,去河邊找鬼宇色。 笑死,一個胖子當著我的面吹牛颁湖,可吹牛的內(nèi)容都是我干的宣蠕。 我是一名探鬼主播,決...
    沈念sama閱讀 39,107評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼甥捺,長吁一口氣:“原來是場噩夢啊……” “哼抢蚀!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起镰禾,我...
    開封第一講書人閱讀 37,845評論 0 268
  • 序言:老撾萬榮一對情侶失蹤皿曲,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后吴侦,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體屋休,經(jīng)...
    沈念sama閱讀 44,299評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,612評論 2 327
  • 正文 我和宋清朗相戀三年备韧,在試婚紗的時候發(fā)現(xiàn)自己被綠了劫樟。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,747評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡织堂,死狀恐怖叠艳,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情易阳,我是刑警寧澤附较,帶...
    沈念sama閱讀 34,441評論 4 333
  • 正文 年R本政府宣布,位于F島的核電站潦俺,受9級特大地震影響拒课,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜黑竞,卻給世界環(huán)境...
    茶點故事閱讀 40,072評論 3 317
  • 文/蒙蒙 一捕发、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧很魂,春花似錦扎酷、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,828評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽谁榜。三九已至,卻和暖如春凡纳,著一層夾襖步出監(jiān)牢的瞬間窃植,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,069評論 1 267
  • 我被黑心中介騙來泰國打工荐糜, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留巷怜,地道東北人。 一個月前我還...
    沈念sama閱讀 46,545評論 2 362
  • 正文 我出身青樓暴氏,卻偏偏與公主長得像延塑,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子答渔,可洞房花燭夜當晚...
    茶點故事閱讀 43,658評論 2 350

推薦閱讀更多精彩內(nèi)容