Литературное программирование Дональда Кнута

Идея Literary Programming
Т.е. пишется как бы текст лекции, статьи, объяснения или эссе, в который вставлены абзацы-куски кода. Это намеренно сделано так, что читается подряд, как связный текст и предназначено в первую очередь для человеческих глаз.

Затем два простеньких инструмента (command-line utilities по 40-60кб, «tangle» и «weave») жуют исходник на «литературном программистском языке», т.е. смеси текста и программы с минимальной, простой разметкой как бы в виде комментариев и выдают — один чистый код (C у Кнута, но Haskel, ML, Perl, …. в поздних утилитах для ЛП — вообще любой язык), второй — красиво отформатированную статью-документацию.

Отличие от обычных схем документирования в том, что его utilities позволяют менять последовательность и логику во время написания программы, освобождая её от машинной, и одновременно создавать любые иерархии абстракций на человеческом языке, которые потом будут правильно развернуты и вставлены в исходники

Кнут выдумал это очень давно, и его оригинальные инструменты работают на основе его же собственного TeX’а (т.е. программист пишет свой исходник-эссе пользуясь TeXовой разметкой), но сегодня есть варианты для, например, «вики-синтаксиса».

Главная идея Кнута в том, что такой стиль СИЛЬНО ПОМОГАЕТ делать ПРОЕКТЫ БОЛЬШОГО РАЗМЕРА. Это — огромная проблема. Человеческий мозг начинает затирать после первых 1000-1300 строчек, приходится сосредоточиваться значительно сильнее чтобы все помнить и не сажать ошибок, и далее приходится вводить особые способы деления на куски, выдумывания новых абстракций более высокого уровня чтобы затем писать на «новом языке» и т.д.

Мой успешный опыт расширения горизонта охвата — «логическое программирование» (Пролог). Кнут утверждает, что «литературное программирование» (literate programming) обладает подобным эффектом
Поясняющий пример

Пример взят из документации программы для «литературного программирования» «noweb» и написан на языке Ц, хотя сама методология работает не привязана ни к одному конкретному языку (и в документации, кстати, отмечалось её успешное применение с перлом)

Для примера давайте рассмотрим HTML-документ созданный из одного классического примера — микро-программы для подсчета букв, слов и строчек в файле, юникс «wc» utility.
Я не привожу разметку исходника (она очень проста), здесь мы прочитаем HTML-форматированную документацию-программу-»эссе»

An Example of noweb

Norman Ramsey
Dept. of Computer Science, Princeton University
Princeton, NJ 08544

Contents

Introduction

The following short program illustrates the use of noweb, a low-tech tool for literate programming. The purpose of the program is to provide a basis for comparing WEB and noweb, so I have used a program that has been published before; the text, code, and presentation are taken from Chapter 12 of D. E. Knuth, Literate Programming (volume 27 of Center for the Study of Language and Information Lecture Notes, Stanford Univ., 1992).

Заметьте, это документ, который написан как эссе, или объяснение, или «мысли во время программирования» — вскрывая логику, т.е. не документ пытающийся после создания программы как-то преставить её той или иной аудитории.

Выпустим кусок текста, интересное начинается ниже.
Заметьте, как авторы программы пишут кусок программного текста вставляя в него строчки-заголовки, на самом деле строчки, описывающие смысл выпущенного куска, и «сворачивающие» текст программы, позволяя читателю выделить главное сейчас, откладывая устройство его частей на потом.
Строчки, служащие заголовками будут раскрыты в другом месте, они — ссылки, а ссылки «используется» и «определение» под отрывком дают возможность читателю увидеть целое.
Не надо понимать так, что это обычные гиперссылки в документации. НЕТ. Главная идея в том, что вы программируете в логическом, выбранном вами порядке, а utilities создадут из него верный исходник, правильный для компилятора или интерпретатора.
Другими словами, программу можно писать в логической последовательности, а не в последовательности предписанной правилами языка.

Now we come to the general layout of the main function.
<The main program>=
main(argc, argv)
  int argc;
    /* number of arguments on UNIX command line */
  char **argv;
    /* the arguments, an array of strings */
{
  <Variables local to main>
  prog_name = argv[0];
  <Set up option selection>
  <Process all the files>
  <Print the grand totals if there were multiple files>
  exit(status);
}

Used above.

If the first argument begins with a `-‘, the user is choosing the desired counts and specifying the order in which they should be displayed. Each selection is given by the initial character (lines, words, or characters). For example, `-cl‘ would cause just the number of characters and the number of lines to be printed, in that order.

We do not process this string now; we simply remember where it is. It will be used to control the formatting at output time.

<Variables local to main>=
int file_count;
  /* how many files there are */
char *which;
  /* which counts to print */

Used above; next definition.

<Set up option selection>=
which = "lwc";
  /* if no option is given, print 3 values */
if (argc > 1 && *argv[1] == '-') {
  which = argv[1] + 1;
  argc--;
  argv++;
}
file_count = argc - 1;

Used above.

Теперь — следующая важная черта. Слишком часто приходится держать в уме слишком много. Например, на языке Ц определения переменных или includes приходится дописывать в начало файла.
«Литературное программирование» позволяет добавлять к уже существующим секциям, из любых мест в файле, где по логике добавления возникают. Заметьте «плюсики» в заголовках в отрывке ниже: мы дописываем в уже существующие и определенные куски те части, которые по логике возникли только сейчас

Now we scan the remaining arguments and try to open a file, if possible. The file is processed and its statistics are given. We use a do ... while loop because we should read from the standard input if no file name is given.
<Process all the files>=
argc--;
do {
  <If a file is given, try to open *(++argv); continue if unsuccessful>
  <Initialize pointers and counters>
  <Scan file>
  <Write statistics for file>
  <Close file>
  <Update grand totals>
    /* even if there is only one file */
} while (--argc > 0);

Used above.

Here’s the code to open the file. A special trick allows us to handle input from stdin when no name is given. Recall that the file descriptor to stdin is 0; that’s what we use as the default initial value.

<Variables local to main>+=
int fd = 0;
  /* file descriptor, initialized to stdin */

Used above; previous and next definitions.

<Definitions>+=
#define READ_ONLY 0
  /* read access code for system open */

Used above; previous and next definitions.

<If a file is given, try to open *(++argv); continue if unsuccessful>=
if (file_count > 0
&& (fd = open(*(++argv), READ_ONLY)) < 0) {
  fprintf(stderr,
    "%s: cannot open file %s\n",
    prog_name, *argv);
  status |= cannot_open_file;
  file_count--;
  continue;
}

Used above.

И, наконец, программа автоматически создает индекс всех ваших «заголовков» (т.е. логических кусков текста которые вы выделили и в собственном порядке описали в «литературной программе»),
а также — тех переменных, которые вы пометили как нужные для индексирования.

Я привел лишь 4 отрывка из всего текста, поэтому не все ссылки будут работать — но те, которые включены в эти отрывки будут. Можете попробовать, например, переменную «which» или кусок «Process all the files». «D» изначает «определение», definition, а «U» — использование, usage.

Index

Chunks

«D» means «defined» , peice by piece
«U» means «used in», again numbered by instance of use

Identifiers

Мы наблюдали результат weave, программы выделяющей из «литературного исходника» форматированный документ. Другая utility, tangle, выделит чистый код, подставив все куски куда надо, содержащий его собственные комментарии (/*………..*/ для Ц), но вычищенный от литературы.

Т.е.

    [1] с помощью этих utilities вы не просто подробно комментируете — вы ПИШЕТЕ В ПОРЯДКЕ СВОЕЙ ЛОГИКИ, и этим его literate programming в принципе отлично от любых систем документаций.[2] Также: oн позволяет то, что вы пишете словами на промокашке как «псевдокод» высокого уровня, когда сочиняете ИСПОЛЬЗОВАТЬ НАПРЯМУЮ КАК ТЕКСТ СОСТОЯЩИЙ ИЗ ПОЛНОЦЕННЫХ МАКРО, в которые его tools подставят все что нужно.
    Иерархии абстракций создаются на уровне слов человеческого языка, произвольными фразами, на как-бы мета-уровне по отношению к разбиениям на самом программном языке

Поэтому-то подход и позволяет, если ему верить, не запутываться в больших и/или сложных программах.

Мне понравилась эта заметка:
"Имидж" дороже денег
Сравнение iPhone 6 и iPhone 5
Как MacBook, но не Mac
Ноутбук Dell XPS 15 L521X
Sony Extra Bass
Отзыв на наушники Sony Extra Bass
Другое:
Литературное программирование Дональда Кнута: 2 комментария
  1. Большой плюс noweb — его универсальность, позволяющая использовать с любыми языками. Плюс для новичков — простота, позволяющая его легко осваивать. Также к плюсам относится и то, что Однако для конкретных языков, для которых уже разработаны свои средства литературного программирования, эти плюсы оборачиваются недостатками, поскольку он
    не учитывает особенностей конкретных языков и не обладает достаточной гибкостью.
    Для языка C целесообразнее всего использовать cweb, а для паскаля — просто web. Впрочем, использоване системы web для русскоязычных пользователей сопряжено и с определёнными трудностями: система разрабатывалась для англоговорящего населения, и во входных файлах русские буквы заменяет пробелами, а обозначает их кодами лексемы.
    Есть русификация этих программ с описанием и примером использования на русском языке. Если заинтересовало, можете посмотреть на сайте http://ibzh.ts6.ru/tex/literate.htm

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

*

Можно использовать следующие HTML-теги и атрибуты: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>