EMACS-DOCUMENT

=============>随便,谢谢

Literate Programming: Empower Your Writing with Emacs Org-Mode

Traditionally, programs are code first with maybe some blocks of prose in the form of code comments. If you then write an article about a program, you might copy some of the code out of that program to illustrate your point. What if we turned this on its head and started with the prose? What if we only wrote the code as it became relevant to the article? What if my blog articles were executable? 传统上,程序是以代码注释的形式编写的。如果你写了一篇关于程序的文章,你可以从程序中拷贝一些代码来阐述你的观点。如果我们反过来从散文开始呢?如果我们只编写与文章相关的代码呢?如果我的博客文章是可执行的呢?

Today, I want to share a programming paradigm that I've been using when I write about software. It's called Literate Programming, and it's changed the way I think about writing. 今天,我想分享一个我在写软件的时候使用过的编程范例。这就是所谓的文字编程,它改变了我对写作的看法。

What is literate programming?

*什么是识字程序?

属性: :CUSTOM_ID: whatisliterateprogramming :CUSTOM_ID whatisliterateprogramming

结束:

What's the difference between writing and programming? When I sit down to write something, I don't typically reach for a pen and paper, but rather sit down at my computer and start rhythmically tapping at the keyboard. It sounds a lot like programming. I'm a software engineer by trade, and in the last few years I've been blogging about programming. 写和编程的区别是什么?当我坐下来写东西时,我通常不会拿笔和纸,而是坐在电脑前,有节奏地敲击键盘。这听起来很像编程。我的职业是软件工程师,过去几年我一直在写关于编程的博客。

I think that there is great potential to enhance both writing and programming by allowing the lines between them to blur from time to time. 我认为,通过允许它们之间的界线不时地模糊化,可以极大地增强编写和编程的能力。

blog_big-cover-image.png blog_big-cover-image.png

Literate programming isn't something that many modern software developers seem to have heard of, but it isn't a new idea. The term was coined in 1983 by Donald Knuth to refer to the new way in which he was laying out his software projects. 许多现代软件开发人员似乎都没有听说过识字编程,但它并不是一个新概念。这个术语是http://www.literateprogramming.com/knuthweb.pdf在1983年由Donald Knuth创造的,用来指他设计软件项目的新方式。

Usually, when you think of how a software project is organized, the first consideration is what the compiler expects. You split things into files and folders in a particular way. You name the functions concisely and without spaces. Software engineering tools have luckily gotten much better since 1983, including neat features like function names longer than six characters. You can even define functions in any order you please, and have clever IDEs figuring out variable types when you hover your mouse over them. The structures that suit the compiler have become more flexible and more human friendly. 通常,当您考虑软件项目是如何组织的时候,首先要考虑的是编译器的期望。你以一种特殊的方式把东西分成文件和文件夹。函数名要简洁,不要空格。幸运的是,自1983年以来,软件工程工具已经有了很大的改进,包括函数名长度超过6个字符这样简洁的特性。您甚至可以按自己喜欢的任何顺序定义函数,并在将鼠标悬停在函数上时使用聪明的ide来确定变量类型。适合编译器的结构变得更加灵活,更加人性化。

For long running projects, there's a non-compiler audience you need to consider: the software engineer who encounters the code you're currently writing. We're still looking at folders full of source code and we're fighting a battle to make it clear to future readers what problem each bit of code is solving. Have you ever needed to debug code that was written five years ago, by someone who has since left the company? When you suspect it isn't working but can't figure out exactly what it was meant to be doing in the first place? 对于长期运行的项目,您需要考虑非编译器受众:遇到您当前正在编写的代码的软件工程师。我们仍然在查看充满源代码的文件夹,我们正在进行一场战斗,以便让未来的读者清楚地了解每段代码解决了什么问题。您是否曾经需要调试五年前由已经离开公司的人编写的代码?当你怀疑它不工作,但又不知道它到底是用来做什么的时候?

Knuth felt that there was a more effective traditional solution to explain these things: books. Imagine if you could hand your new coworker a book and say “this explains exactly how our system works”. Knuth also created the TeX typesetting system, so he was in the perfect position to come up with a clever scheme to combine writing prose and writing code: Knuth认为有一种更有效的传统方法来解释这些事情:书籍。想象一下,如果你能把一本书递给你的新同事,并说:“这正好解释了我们的系统是如何工作的。”Knuth还创建了TeX排字系统,所以他处于一个完美的位置,提出了一个巧妙的方案,将写散文和写代码结合起来:

The source code for a literate program looks much more like a document than normal source code. The key feature is that there are blocks of code embedded directly into the document. You can pass your literate program to one of two compilers. 一个“识字程序”的源代码看起来比一般的源代码更像一个文档。关键的特性是有一些代码块直接嵌入到文档中。你可以把你的读写程序传给两个编译器中的一个。

The first compiler produces a nicely typeset human readable document (more recently a nicely typeset human readable web page). That would be the document you're reading right now. If I drop in a block of JavaScript, it might look something like this: 第一个编译器生成一个排版良好的人类可读文档(最近是一个排版良好的人类可读web页面)。那就是你现在正在阅读的文件。如果我放入一个JavaScript块,它可能是这样的:

console.log('Hello world!');

The second compiler takes just the code blocks, stitches them together, and calls the normal compiler. For JavaScript, that means calling Node JS. I could run that program, and get the expected salutation. 第二个编译器只获取代码块,将它们拼接在一起,然后调用普通的编译器。对于JavaScript,这意味着调用Node JS。我可以运行那个程序,并得到预期的问候语。

Hello world!

To go beyond a hello world example, I recently wrote an article where I explained how Monte Carlo simulations work. In the article, I had a code block with an example written in the Rust programming language. It used a Monte Carlo simulation to calculate Pi. I could compile and execute that blog article to run the simulation and show the results. I could even automatically insert the console output from the simulation into the article itself. 为了超越hello world的例子,我最近写了一篇文章[[https://www.worit.co.za/programming/2018/03/28/moncarlo -simulations.html],在这篇文章中我解释了蒙特卡洛模拟是如何工作的。在本文中,我用Rust编程语言编写了一个代码块和一个示例。采用蒙特卡罗模拟计算Pi。我可以编译并执行那篇博客文章来运行模拟并显示结果。我甚至可以将模拟的控制台输出自动插入到文章中。

In other words, you write a document that describes your program, and that document is also the source code for the program being described. 换句话说,您编写了一个描述程序的文档,该文档也是所描述程序的源代码。

My literate toolbox: Emacs Org-mode

*我的识字工具箱:Emacs组织模式

属性: :CUSTOM_ID: myliteratetoolboxemacsorgmode :CUSTOM_ID myliteratetoolboxemacsorgmode

结束:

For literate programming, I use a language called Org-mode. I know, the name is a bit strange, but it makes more sense if you consider its history. Org-mode started as an extension for the text editor Emacs that helped to organize notes. Emacs users have found it so useful that now it's part of the base install. 对于文字编程,我使用一种叫做Org-mode的语言。我知道,这个名字有点奇怪,但如果你考虑到它的历史,它更有意义。Org-mode作为文本编辑器Emacs的扩展启动,帮助组织注释。Emacs用户发现它非常有用,现在它已经成为基础安装的一部分。

At its heart, Org-mode is a plain text format similar to Markdown. You put some stars at the beginning of a line and suddenly that line is considered a heading! The organization elements come in where you start a line with TODO and suddenly that line is an item on your to-do list. I could easily fill a series of articles on things I do with Org-mode, but for today I'm going to focus on its literate programming support. org模式的核心是一种类似于Markdown的纯文本格式。你把一些星星放在一行的开始,突然之间,这行被认为是标题!组织元素出现在你用TODO开始一行的地方,突然这一行变成了你的待办事项列表中的一个项目。我可以很容易地完成关于我使用Org-mode所做事情的一系列文章,但是今天我将重点讨论它的文字编程支持。

When you want to export your Org-mode file for people to read, it supports many different formats. This means it can be a good option regardless of where you need the notes to go in the end. I personally use three: 当您想要导出您的组织模式文件供人们阅读时,它支持许多不同的格式。这意味着无论你最后需要把钱放在哪里,这都是一个不错的选择。我个人使用三个:

  • HTML for my website,
  • HTML为我的网站,
  • PDF (via LaTeX) if I want something printable and
  • PDF(通过乳胶),如果我想打印的东西
  • HTML in reveal.js format, for when I'm making presentation slides.
  • HTML在reveal.js格式,当我做演示幻灯片。

In terms of programming languages, Org-mode supports writing code blocks in a great many programming languages, including a template to add support for your favourite one. 在编程语言方面,Org-mode支持在非常多的编程语言中编写代码块,包括一个为您最喜欢的语言添加支持的模板。

All of this becomes a lot more relatable with an example. 所有这些都与一个例子有很大的关系。

Let's write a quick literate program

让我们写一个快速的识字程序

属性: :CUSTOM_ID: letswriteaquickliterateprogram :CUSTOM_ID letswriteaquickliterateprogram

结束:

For this example, say that you're teaching a course. You have a class list of students, and the marks that they received. You need to write up a report on which students passed and which failed. Additionally, you need to calculate some statistics to get an idea of how well the course went. 对于这个例子,假设您正在教授一门课程。你有一个学生的班级名单,以及他们的分数。你需要写一份报告,说明哪些学生及格了,哪些没有及格。此外,您需要计算一些统计数据来了解课程进展情况。

Rather than reaching for separate writing and programming tools, you decide to do your report as a literate program. 你决定把你的报告写成一个文字程序,而不是使用单独的编写和编程工具。

I know that this is an overly simplistic example. This obviously doesn't show Org-mode working at its limits, but rather just a silly example to get you thinking about what's possible. 我知道这是一个过于简单的例子。很明显,这并没有显示出组织模式的极限,而只是一个愚蠢的例子,让你思考什么是可能的。

Setting up your environment

设置您的环境

属性: :CUSTOM_ID: settingupyourenvironment :CUSTOM_ID settingupyourenvironment

结束:

I'm going to use JavaScript as the programming language in this report. It's a fairly well known language, and its dynamic nature means that the examples don't get as bogged down in ceremony. 我将在这个报告中使用JavaScript作为编程语言。这是一种相当有名的语言,它的动态性意味着示例不会拘泥于繁文缛节。

If you're following along in Emacs, you'll need to enable the integration between Org-mode and JavaScript. You can do this by adding the following line to your Emacs config: 如果您正在学习Emacs,则需要启用org模式和JavaScript之间的集成。你可以在Emacs配置中添加以下代码:

(require 'ob-js)

You also need to have Node.JS installed on your computer. This is the normal situation for any programming language you want to support in Org-mode. First, you need the tools to execute that language installed on your computer. Then, you need to tell Emacs how to call it by adding something like that require statement to your Emacs config. 您还需要在您的计算机上安装Node.JS。这是您希望在org模式中支持的任何编程语言的正常情况。首先,您需要执行安装在计算机上的语言的工具。然后,您需要通过向Emacs配置添加类似于require语句的内容来告诉Emacs如何调用它。

Finding data to work with

查找要使用的数据

属性: :CUSTOM_ID: findingdatatoworkwith :CUSTOM_ID findingdatatoworkwith

结束:

The first thing that you'll need to do is get the data that you're interested in working on into Org-mode. You also need to name the table, so that you can refer to it in scripts later. I've named this table “students”. This is the syntax for a table: 您需要做的第一件事是将您感兴趣的数据转换为org模式。您还需要为表命名,以便以后在脚本中引用它。我把这张桌子命名为“学生”。这是一个表的语法:

#+NAME: students
| Name | Mark |
|--------+------|
| Alice | 79 |
| Bob | 19 |
| Claire | 50 |
| Dave | 49 |
| Eve | 87 |
| Frank | 73 |

Org-mode makes it easy to create a table from CSV if you happen to already have the data in a different format. 如果您碰巧已经有了不同格式的数据,那么使用Org-mode可以很容易地从CSV创建一个表。

Once you export it, it's just a normal table. 导出之后,它只是一个普通的表。

table-1.png https://offerzen.ghost.io/content/images/2018/05/table - 1. png

Our first code block: what does it mean to pass a course?

**我们的第一个代码块:通过一门课程意味着什么?

属性: :CUSTOM_ID: ourfirstcodeblockwhatdoesitmeantopassacourse :CUSTOM_ID ourfirstcodeblockwhatdoesitmeantopassacourse

结束:

Let's start writing some code. The first thing you're going to do is to write a function to determine if someone has passed. In a real course, maybe you need to add up marks from multiple assignments, or maybe students need to pass all of the assignments leading up to the exam as well as the exam itself. 让我们开始编写一些代码。您要做的第一件事是编写一个函数来确定是否有人通过。在真正的课程中,也许你需要把多项作业的分数加起来,或者也许学生需要通过考试前的所有作业以及考试本身。

The beauty of it just being a code block is that the function can get as complicated or simple as it needs to be. 代码块的美妙之处在于,函数可以根据需要变得复杂或简单

For your class, a student has passed if their mark is more than 50%, plus an extra 5% required for every letter of their name. Bob and Eve are faster names to type, so their marking can be more lenient. You should also give this code block a name so you can reference it later. I'm naming it “passes functions”. 在你的课上,如果一个学生的分数超过了50%,那么他就通过了考试,并且他的名字的每个字母都需要额外的5%的分数。Bob和Eve的名字键入速度更快,因此它们的标记可以更宽松。您还应该为这个代码块指定一个名称,以便以后引用它。我把它命名为“传递函数”。

This weird logic for marking is something that you might code up and then forget about. 这种奇怪的标记逻辑可能是您编写代码后就会忘记的。

One of the strengths of literate programming is that it gives you space to capture business decisions and the reasoning behind them. 读写式编程的优点之一是,它为您提供了捕获业务决策及其背后的推理的空间。

The Org-mode syntax looks like this: 组织模式的语法是这样的:

#+NAME: passes functions
#+BEGIN_SRC js
function isPass(student) {
return student.mark >= requiredMark(student);
}

function requiredMark(student) {
return 50 + student.name.length 0_sync_master.sh 1_add_new_article_manual.sh 1_add_new_article_newspaper.sh 2_start_translating.sh 3_continue_the_work.sh 4_finish.sh 5_pause.sh base.sh parse_url_by_manual.sh parse_url_by_newspaper.py parse_url_by_newspaper.sh project.cfg reformat.sh texput.log urls_checker.sh 5;
}
#+END_SRC

With all of the Org-mode examples here, I'm including both the Org-mode source code and the results of exporting it. Whenever you see #+BEGIN_SRC js, you're looking at Org-mode source code. The “js” tells Org-mode that it's JavaScript code. 对于这里的所有组织模式示例,我同时包含了组织模式源代码和导出它的结果。当你看到=#+BEGIN_SRC js=时,你看到的是org模式的源代码。“js”告诉Org-mode它是JavaScript代码。

Like with the table, it's rendered into your exported HTML report, complete with appropriate syntax highlighting. 与表一样,它被呈现到导出的HTML报告中,并具有适当的语法高亮显示。

function isPass(student) {
var name = student[0];
var mark = student[1];
return mark >= requiredMark(name);
}

function requiredMark(name) {
return 50 + name.length 0_sync_master.sh 1_add_new_article_manual.sh 1_add_new_article_newspaper.sh 2_start_translating.sh 3_continue_the_work.sh 4_finish.sh 5_pause.sh base.sh parse_url_by_manual.sh parse_url_by_newspaper.py parse_url_by_newspaper.sh project.cfg reformat.sh texput.log urls_checker.sh 5;
}

Let's find out who passed

让我们看看谁通过了

属性: :CUSTOM_ID: letsfindoutwhopassed :CUSTOM_ID letsfindoutwhopassed

结束:

Having set up a table of students as well as a way to tell if they pass, you now need to make a new table that lists the passes and failures. 设置了一个学生表以及一种判断他们是否通过的方法之后,现在需要创建一个新表,列出通过和失败。

This code block uses two new things. The first is that I've declared a variable in the header of the code block called “students”, and pass in the students table from earlier. The second is that I use “noweb” syntax (named after Knuth's Web program that he wrote for literate programming), to inject my passes functions into the code block. You can think of it as the compiler copying the “passes functions” block and pasting it in the “<<passes functions>>” in this block. 这个代码块使用了两个新东西。首先,我在代码块的头部声明了一个名为“students”的变量,并传递了前面的students表。第二,我使用“noweb”语法(以Knuth为读写编程编写的Web程序命名)将我的pass函数注入代码块。你可以把它想象成编译器复制“传递函数”块,然后把它粘贴到这个块中的=“”=中。

#+NAME: passing students
#+BEGIN_SRC js :var students=students :noweb yes :exports both
<<passes functions>>

return students.map(function(student) {
var name = student[0];
var pass = isPass(student) ? 'Passed' : 'Failed';
return [
name,
pass
];
});
#+END_SRC

When you export, the headers from the code blocks aren't rendered. A reader won't necessarily know what the passes functions are. Usually, this isn't a problem because you can clarify this in your prose. 导出时,不会呈现代码块的标题。读者不一定知道传递函数是什么。通常,这不是一个问题,因为你可以在你的文章中阐明这一点。

This function returns a two dimensional array. When you run it, Org-mode will take the returned value and inject it into the file for you. The “exports both” header indicates that you want to include both the code block and the result in your report. 这个函数返回一个二维数组。当您运行它时,Org-mode将获取返回值并将其注入到文件中。“export both”报头表示您希望在报告中同时包含代码块和结果。

<<passes functions>>

return students.map(function(student) {
var name = student[0];
var pass = isPass(student) ? 'Passed' : 'Failed';
return [
name,
pass
];
});

table-2-1.png https://offerzen.ghost.io/content/images/2018/05/table - 2 - 1. - png

To get an idea for just how awesome this is, take a look at this clip of me changing and then rerunning the code. 要想知道这有多棒,看看这段我修改并重新运行代码的剪辑。

eval-demo.gif eval-demo.gif

The table is just another Org-mode table. You could have another code block reading in the results of this one. It even works if your second code block is a different programming language. This lets you use different programming languages for their various strengths. Have a program written in C++ that generates data but you want to analyze the data using R? After you're done with the analysis you want to use Gnuplot or Graphviz to represent your findings graphically? Org-mode has you covered! 该表只是另一个组织模式表。您可以在这个结果中读取另一个代码块。即使您的第二个代码块是另一种编程语言,它也可以工作。这使您可以使用不同的编程语言来实现它们的不同功能。有一个程序写在c++生成数据,但你想分析数据使用R?在您完成分析之后,您想要使用Gnuplot或Graphviz来图形化地表示您的发现吗?组织模式已经覆盖你了!

Using code that hasn't appeared yet

*使用尚未出现的代码

属性: :CUSTOM_ID: usingcodethathasntappearedyet :CUSTOM_ID usingcodethathasntappearedyet

结束:

Sometimes, when you're writing a report, you want to skip straight to your results. In this section, let's jump straight to showing the average and standard deviation of the marks. 有时候,当你写报告的时候,你想直接跳到你的结果。在本节中,让我们直接跳到显示标记的平均和标准偏差。

Count: 6
Average: 60
Standard deviation: 25

The Org-mode code that generates the results looks like this: 生成结果的组织模式代码如下:

#+NAME: overall statistics
#+BEGIN_SRC js :var students=students :noweb yes :exports both :results output
<<statistics functions>>

var marks = students.map(function(student) {
return student[1];
});
console.log('Count:', marks.length);
console.log('Average:', average(marks));
console.log('Standard deviation:', standardDeviation(marks));
#+END_SRC

When you execute this block for the first time, Org-mode will inject the console output from your code into the report below your code block. Crucially, the results will have a header indicating the name of the code block that produced it. In Org-mode, it looks a bit like this: 当您第一次执行这个代码块时,Org-mode会将您代码中的控制台输出注入到代码块下面的报告中。至关重要的是,结果将有一个标题,指示生成它的代码块的名称。在组织模式下,它看起来有点像这样:

#+RESULTS: overall statistics
: Count: 6
: Average: 60
: Standard deviation: 25

You can then move the results block to wherever you want in your report: 你可以把结果块移动到你想要的地方:

In a literate program, the code blocks and their results are linked through their names. They don't need to appear in a particular order in the report. 在读写程序中,代码块及其结果通过它们的名称链接。它们不需要在报告中以特定的顺序出现。

This frees you up to organize the code in your report as would make most sense to a reader. You can even update and rerun the code and see the results update! 这使您可以自由地组织报告中的代码,这对读者来说是最有意义的。您甚至可以更新和重新运行代码,并看到结果更新!

In the end, I have my code block that produced those results down here, but the results are a few paragraphs up. 最后,我的代码块产生了这些结果,但结果是几段向上。

<<statistics functions>>

var marks = students.map(function(student) {
return student[1];
});
console.log('Count:', marks.length);
console.log('Average:', average(marks));
console.log('Standard deviation:', standardDeviation(marks));

You might notice that I used a code block here that hasn't been introduced yet: The code that actually does the average and standard deviation calculations is in a code block later on called “statistics functions”. 您可能注意到,我在这里使用了一个还没有介绍的代码块:实际上执行平均和标准偏差计算的代码稍后位于一个名为“统计函数”的代码块中。

When I was in university, my project reports had strict page limits. My entire report had to fit into 5 pages. I was, however, allowed to include an appendix for peripheral details of importance, such as: 我上大学的时候,我的项目报告有严格的页数限制。我的整个报告只有5页纸。然而,我被允许在附录中加入一些重要的外围细节,比如:

  • Raw data,

原始数据,

  • Full code listings and

-完整的代码清单和

  • Blocks of code explaining how to implement well-known statistical functions in JavaScript.

-代码块解释如何实现众所周知的统计功能在JavaScript。

I use the "statistics functions" code block in a very similar manner. 我以非常相似的方式使用“统计函数”代码块。

Excluding statistics functions from your report

**在报告中不包括统计功能

属性: :CUSTOM_ID: excludingstatisticsfunctionsfromyourreport :CUSTOM_ID excludingstatisticsfunctionsfromyourreport

结束:

As promised, the statistics functions have to be somewhere in the report. I've included them here, but I've chosen to set the exports header to “none”, so that it wouldn't be included in the HTML export. For the sake of this example, I'm saying that these functions aren't particularly important to readers. 正如所承诺的,统计功能必须位于报告中的某个位置。我在这里包含了它们,但是我选择将exports头设置为“none”,这样它就不会包含在HTML导出中。对于这个例子,我是说这些函数对读者来说不是特别重要。

#+NAME: statistics functions
#+BEGIN_SRC js :exports none
function average(marks) {
return Math.round(marks.reduce(function(accumulator, next) {
return accumulator + next;
}, 0) / marks.length);
}

function standardDeviation(marks) {
var marksAverage = average(marks);
var sd = Math.sqrt(marks.reduce(function(accumulator, next) {
return accumulator + Math.pow(next - marksAverage, 2);
}, 0) / (marks.length - 1))
return Math.round(sd);
}
#+END_SRC

Time to Tangle

*打结时间

属性: :CUSTOM_ID: timetotangle :CUSTOM_ID timetotangle

结束:

The term “tangling” is another word borrowed from Knuth. He named his literate programming tool Web because the connections between code blocks are so web-like. That's why, when you compile a web program into a human-readable document, it's called weaving. 术语“缠结”是另一个从Knuth借用的词。他将自己的读写编程工具命名为Web,因为代码块之间的连接非常类似于Web。这就是为什么当你将一个web程序编译成一个人类可读的文档时,它被称为编织。

When you compile a web program to an executable program, it's called tangling. *当你把一个网络程序编译成一个可执行程序时,这叫做纠缠

Whenever I want to test a code block for my articles, the Org-mode file is tangled and executed. When I want to view the article in my web browser, the Org-mode files are weaved to produce my website. 每当我想要为我的文章测试一个代码块时,org模式的文件就会被纠缠并执行。当我想在我的web浏览器中查看文章时,组织模式的文件被织入以生成我的网站。

In this example, I focussed on letting Org-mode take the code block and execute it. If you add the “tangle” header to a code block, you can tell Org-mode to write it out as a file. This can be particularly useful if you're writing one literate file as part of a larger project. 在本例中,我主要关注于让org模式获取代码块并执行它。如果将“tangle”头信息添加到代码块中,可以告诉Org-mode将其作为文件写入。如果您正在编写一个读写文件作为大型项目的一部分,那么这将特别有用。

#+BEGIN_SRC js :tangle passCalculator.js
function isPass(student) {
var name = student[0];
var mark = student[1];
return mark >= requiredMark(name);
}
// Other JavaScript here as before
#+END_SRC

After telling Org-mode to tangle this code block, it will be written out to the file passCalculator.js. This is particularly useful if you have an existing system that you're extending using literate programming. You can write your new files in Org-mode, and have it tangle your code blocks into the appropriate file structure for your\ existing system. 现有的系统。

What are the benefits of literate programming?

*读写式编程有什么好处?

属性: :CUSTOM_ID: whatarethebenefitsofliterateprogramming :CUSTOM_ID whatarethebenefitsofliterateprogramming

结束:

At this point, you might be asking yourself why you should put in the effort to learn a new tool. Well, as Knuth said, “Surely nobody wants to admit writing an illiterate program.” Jokes aside, if you spend your time writing prose, you might be suspicious of bringing executable code into your writing. On the other hand, if you spend your time writing software, you might be suspicious of bringing in more documentation. Let's look at the benefits to both sides: 此时,您可能会问自己为什么要花精力学习新工具。正如Knuth所说,“当然没有人愿意承认自己写了一个文盲程序。撇开笑话不谈,如果你把时间花在写散文上,你可能会对把可执行代码带到你的写作中产生怀疑。另一方面,如果您把时间花在编写软件上,您可能会对引入更多的文档有所怀疑。让我们看看双方的好处:

As a developer, I think the benefits that literate programming can bring for everyday programming have been slowly eroded by advancements in modern language design. However, literate programming is still valuable if your problem domain is very complicated. Well written code alone is very good at explaining what it is doing, but very bad at explaining why it's doing it. 作为一名开发人员,我认为读写式编程给日常编程带来的好处已经被现代语言设计的进步慢慢侵蚀了。然而,如果您的问题域非常复杂,识字编程仍然是有价值的。编写良好的代码本身就非常善于解释它在做什么,但却非常不善于解释它为什么这样做。

If you don't understand the why, you will have a particularly miserable time if you need to adjust the code to meet changing requirements. 如果您不理解其中的原因,那么当您需要调整代码以满足不断变化的需求时,您将会非常痛苦。

Suppose you're writing a library that makes heavy use of some particular mathematical theory. Everything would be much clearer to a future programmer if they knew about the theory first. Literate programming's focus on organizing the program to be read like a book could be extremely valuable. Recently, I wrote a financial planning library at work. Even though it isn't that much code, it was the result of a few months of back and forth with an expert in our business domain. 假设您正在编写一个大量使用某些特定数学理论的库。对于未来的程序员来说,如果他们先了解了这个理论,一切就会清楚得多。读写式编程的重点在于把程序组织得像读一本书一样,这可能非常有价值。最近,我在工作中写了一个财务规划图书馆。尽管它没有那么多代码,但它是我们与业务领域的专家几个月来反复讨论的结果。

Code alone cannot hope to capture all of the derivations, reasoning and trade offs that went into the final result. 代码本身不可能捕获最终结果中的所有派生、推理和权衡。

bear-reading.png bear-reading.png

The writing side is where I've personally seen the most benefit, which I group broadly under the term “reproducible research”. If you're writing a report that at any point references some number crunching, having the actual code that did the number crunching in your document makes it easier for readers to understand how you reached your conclusions. It also makes it much easier to rerun your calculations if a bug is found. I also find that having the code as part of the document lets you jump between describing what you need to do and implementing it, without having to make quite as big context switches. *写作方面是我个人看到的最大的好处,*我把它概括为“可重复研究”。如果您正在编写的报告在任何时候都引用了一些数字处理,那么在文档中使用实际的代码处理这些数字将使读者更容易理解您是如何得出结论的。如果发现错误,它还使重新运行计算变得更加容易。我还发现,将代码作为文档的一部分可以让您在描述需要做什么和实现它之间跳转,而不必进行非常大的上下文切换。

These are the same benefits that you might get by using a spreadsheet. If you're already in a spreadsheet, you're much more likely to drop in a calculation here and there, and let the computer do the heavy lifting. Once your calculations are there, future readers can see how you reached your conclusions. In fact, you could probably consider spreadsheets to be a form of literate programming. 这些都是使用电子表格可能获得的相同好处。如果你已经在一个电子表格中,你更有可能在这里或那里插入一个计算,让计算机来完成繁重的工作。一旦你计算好了,未来的读者就能看到你是如何得出结论的。事实上,你可能认为电子表格是一种文字编程的形式。

What about the downsides of literate programming?

*文化编程的负面影响呢?

属性: :CUSTOM_ID: whataboutthedownsidesofliterateprogramming :CUSTOM_ID whataboutthedownsidesofliterateprogramming

结束:

Up to now, I've been talking about literate programming as if it's a magic panacea that will solve all of your software engineering woes. Unfortunately, this isn't the case with any technology or programming paradigm. 到目前为止,我一直在讨论读写式编程,就好像它是解决所有软件工程问题的灵丹妙药一样。不幸的是,这不是任何技术或编程范例的情况。

Sometimes as a software developer, the majority of your application is fairly obvious. There are many web applications that take data from a user and store it in a database without any special processing. In these cases, the extra overhead of writing thorough documentation probably isn't worth the effort. *有时作为一个软件开发人员,*你的应用程序的大部分是相当明显的。有许多web应用程序从用户获取数据并将其存储在数据库中,而不进行任何特殊处理。在这些情况下,编写完整的文档的额外开销可能不值得这样做。

As software developers, we have a nasty habit of letting any existing documentation get out of date. Writing your software as a literate program needs to come with a strong commitment to keeping that documentation up to date. Unfortunately, having a good understanding of what the software used to do isn't always useful. Having the code and documentation together in one tools helps, but it doesn't take away the extra effort needed. 作为软件开发人员,我们有一个让任何现有文档过期的坏习惯。把你的软件写成一个有文化的程序需要有一个坚定的承诺来保持文档的更新。不幸的是,很好地理解过去使用的软件并不总是有用的。将代码和文档放在一个工具中会有所帮助,但这并不会减少所需的额外工作。

On the writing side, the main issue is that literate programming tends to tie your writing into the tools that support your literate programming. This can make collaboration on a document difficult if the people you're collaborating with are not as sold on the tools as you are. The moment you need to work with a business person who prefers to use Google Docs to share a document, or a university department that insists on receiving drafts as Microsoft Word documents, you start to face the pain of exporting to those proprietary formats. Like many issues in software development, this is really a social issue: for literate programming to work, all of the writers need to agree on the tools being used. *在写作方面,*主要的问题是文学编程倾向于把你的写作与支持你的文学编程的工具联系起来。如果与您协作的人不像您那样对工具感兴趣,这可能会使文档协作变得困难。当你需要与一个喜欢使用谷歌文档共享文档的商业人士合作,或者一个大学部门坚持接收作为Microsoft Word文档的草稿时,你就开始面临向这些专有格式导出文档的痛苦。就像软件开发中的许多问题一样,这确实是一个社会问题:为了使文字编程能够工作,所有的作者都需要对所使用的工具达成一致。

Coding is a social activity

*编码是一种社交活动

属性: :CUSTOM_ID: codingisasocialactivity :CUSTOM_ID codingisasocialactivity

结束:

Hopefully, I've been able to show you that it's worth your time to take a look at literate programming and Org-mode. It can make your programming more expressive. It can give your writing the powers of your favourite programming language. 希望我已经向你们展示了值得你们花时间去看看文字编程和组织模式。它可以使你的程序更有表现力。它可以给你的写作带来你最喜欢的编程语言的力量。

And most of all, in all of this jargon and code, don't forget the human aspect of programming. When you're pushing to get another feature out or squash another bug, it's easy to get tunnel vision and see only the code in front of you. 最重要的是,在所有这些术语和代码中,不要忘记编程的人性方面。当你想要推出另一个功能或者消除另一个bug时,很容易产生狭隘的想法,只看到你面前的代码。

Sit up and look at the people around you. They are the ones that you're writing your code for. 坐起来,看看你周围的人。它们是您编写代码的对象。

The code you're writing today has the potential to be easy for them to understand and a pleasure to work with. As my coworkers will attest, I don't always manage to get this right. When I manage to write code that others enjoy working with, that is a particularly rewarding feeling. 您现在所编写的代码有潜力使他们更容易理解并乐于使用。我的同事可以证明,我并不是总能做到这一点。当我设法编写别人喜欢使用的代码时,这是一种特别有益的感觉。

Remember literate programming. It might not be the best solution to every problem you encounter, but sometimes it is exactly what you need. 记得文学编程。它可能不是您遇到的每个问题的最佳解决方案,但有时它确实是您所需要的。

Addendum: What if I don't like Emacs?

*补充:如果我不喜欢Emacs怎么办?

属性: :CUSTOM_ID: addendumwhatifidontlikeemacs :CUSTOM_ID addendumwhatifidontlikeemacs

结束:

Ok, I admit, Emacs isn't everyone's cup of tea. It's an expert friendly tool with a steep difficulty curve. If you don't have the time or patience to go through the process of learning Emacs, there are other options available. 好吧,我承认,Emacs并不是每个人都喜欢的。这是一个专家友好的工具,具有陡峭的难度曲线。如果您没有时间或耐心完成学习Emacs的过程,那么还有其他的选择。

Spreadsheets

*电子表格

属性: :CUSTOM_ID: spreadsheets :CUSTOM_ID:电子表格

结束:

The easiest option is to use a spreadsheet program. Spreadsheets are more capable than most people realize. They have a broad array of built-in functions, they're interactive, and people you're collaborating with have probably used one before so they'll be able to follow what's going on. 最简单的选择是使用电子表格程序。电子表格比大多数人意识到的更有用。它们有大量的内置函数,它们是交互式的,与您协作的人可能以前使用过它们,所以他们能够跟踪正在发生的事情。

For me, they fall flat on two points: 对我来说,他们在两点上失败了:

  • They're clunky when you're trying to do something complicated that isn't already supported out of the box.

-当你试图做一些复杂的事情时,他们是笨拙的,不支持开箱即用。

  • It's difficult to export the code itself rather than the results.

-很难导出代码本身而不是结果。

Haskell, and other languages that just support it

Haskell,以及其他支持它的语言

属性: :CUSTOM_ID: haskellandotherlanguagesthatjustsupportit :CUSTOM_ID haskellandotherlanguagesthatjustsupportit

结束:

It's a bit uncommon, but some compilers already support literate programming. I don't personally use Haskell, but apparently you just need to use the .lhs file extension rather than the usual .hs. 这有点不常见,但是一些编译器已经支持读写式编程了。我个人并不使用Haskell,但显然您只需要使用.lhs文件扩展名,而不是通常的.hs。

Online document editors

**在线文档编辑器

属性: :CUSTOM_ID: onlinedocumenteditors :CUSTOM_ID onlinedocumenteditors

结束:

Jupyter lets you create notebooks that have embedded Python, Julia or R code. It's different from Emacs and Org-mode in that it runs entirely in your web browser. Jupyter允许您创建嵌入Python、Julia或R代码的笔记本。它与Emacs和org模式的不同之处在于它完全运行在您的web浏览器中。

Tech.io also lets you create documents with embedded code blocks in your browser. It's meant primarily as a tutorial and documentation site, so readers are able to modify and rerun the code blocks themselves. This approach can be fantastic for documentation that explains how to use the code you've written. [[https://tech.io/][科技。也允许你在浏览器中创建嵌入代码块的文档。它主要是作为一个教程和文档站点,因此读者可以自己修改和重新运行代码块。这种方法对于解释如何使用您编写的代码的文档非常有用。

Command line applications

**命令行应用程序

属性: :CUSTOM_ID: commandlineapplications :CUSTOM_ID commandlineapplications

结束:

If you like working in a text editor but don't like Emacs, then finding a command line application could be the right option for you. 如果您喜欢在文本编辑器中工作,但不喜欢Emacs,那么寻找命令行应用程序可能是您的正确选择。

You might still be able to find Knuth's original application called Web, but Knuth himself has moved on to a newer version called CWeb. 你可能还能找到Knuth最初的Web应用程序,但是Knuth自己已经转移到一个更新的版本,叫做CWeb

If you go looking, you'll find a few more variants with the same play on words, such as Noweb, which tries to be simpler to use than Web. 如果你去找的话,你会发现有更多的变体在单词上有相同的用法,比如noweb,它试图比Web使用起来更简单。

How can I learn more?

我怎样才能学到更多?

属性: :CUSTOM_ID: howcanilearnmore :CUSTOM_ID howcanilearnmore

结束:

If you're thinking of trying out literate programming after reading this, maybe one of these links will help you to find a good next step: 如果你读了这篇文章后想尝试一下文字编程,也许其中的一个链接会帮助你找到一个好的下一步: