Андрей Власовских

Блог Андрея Власовских

Литературный Python

5 комментариев

Под впечатлением Literate Haskell, я решил сделать что-то подобное для Python, чтобы было проще писать заметки в блоге. Пишу я редко, поэтому это было стимулом повозиться с блогом и написать что-нибудь.

Literate programming, литературное программирование — идея, придуманная и реализованная Дональном Кнутом в 1980-x для C и TEX:

Главная идея — рассматривать программу как средство взаимодействия между людьми, а не набор инструкций для компьютера.

Идею Кнута реализовали и в Haskell. Там поддерживается два стиля разделения кода и текста: добавление к строкам кода > (птичий стиль) или окружение кода парами \begin{code} и \end{code} (стиль LATEX). К тому же для Haskell часто применяют преобразователи кода из ASCII в расширенный математический набор символов, из-за чего код выглядит неприлично красивым :)

Для меня целью было получить хотя бы некоторые преимущества литературного программирования для Python. Я хотел иметь возможность запускать код, который я пишу в заметках для блогов. Раньше приходилось писать его в отдельном исходнике, затем перенося в заметку, либо полагаться на то, что код написан правильно и запускать его не нужно.

Когда я пишу заметки в блог, я размечаю текст при помощи XHTML или (намного чаще) Markdown. В последнем случае при помощи утилиты markdown я перевожу разметку в XHTML. Для автоматизации я использую GNU make: здесь нужен совсем простой makefile. Для себя я придумал довольно простой способ написания текста в Literate Python. Для разделения кода я использовал птичий стиль Haskell. Исходный файл *.lpy автоматически преобразуется при помощи make в два файла: обычный исходник *.py и файл *.xhtml.

Приведу пример. Вначале код Literate Python, файл example.lpy:

<!-- vi:set tw=80 ts=4 filetype=python: -->

Немного кода *Literate Python*, по мотивам [Literate Haskell][lit-hs]. Вначале
определим функцию возведения в квадрат и комбинатор композиции функций:

  [lit-hs]: http://www.haskell.org/haskellwiki/Literate_programming

> sqr = lambda x: x * x
> o = lambda f, g: lambda x: f(g(x))

В Haskell функция `o` была бы записана как инфиксный оператор `∘`: `f ∘ g = f
g` (если я не ошибаюсь). В Unicode ∘ — это символ U+2218 RING OPERATOR. Кстати,
в Python 3.0 станут возможными идентификаторы Unicode.

А это простой тест модуля. Вначале получаем функцию `hex_square`, которая
является композицией `hex` и `sqr`:

> if __name__ == '__main__':
>     hex_square = o(hex, sqr)

Затем красиво печатаем список квадратов первых 30 числел ≥ 0:

>     from pprint import pprint
>     pprint(list(hex_square(x) for x in xrange(30)))

На этом пример заканчивается.

Вот файл Makefile, при помощи которого из example.lpy получаются example.py и example.xhtml:

XHTMLS = example.xhtml
PYS = example.py
ALL = $(XHTMLS) $(PYS)

%.xhtml: %.lpy
    echo "<div xmlns='http://www.w3.org/1999/xhtml'>`sed 's/^> \(.*\)$$/    \1/' \
        $< | markdown`</div>" > $@

%.py: %.lpy
    sed -n 's/^> \(.*\)$$/\1/p' $< > $@

all: $(ALL)

clean:
    rm -f $(ALL)

А вот результаты. Файл example.py:

sqr = lambda x: x * x
o = lambda f, g: lambda x: f(g(x))
if __name__ == '__main__':
    hex_square = o(hex, sqr)
    from pprint import pprint
    pprint(list(hex_square(x) for x in xrange(30)))

И файл example.xhtml:

<div xmlns='http://www.w3.org/1999/xhtml'>
<!-- vi:set tw=80 ts=4 filetype=python: -->

<p>Немного кода <em>Literate Python</em>, по мотивам <a
href="http://www.haskell.org/haskellwiki/Literate_programming">Literate
Haskell</a>. Вначале определим функцию возведения в квадрат и комбинатор
композиции функций:</p>

<pre><code>sqr = lambda x: x * x
o = lambda f, g: lambda x: f(g(x))
</code></pre>

<p>В Haskell функция <code>o</code> была бы записана как инфиксный оператор
<code>∘</code>: <code>f ∘ g = f g</code> (если я не ошибаюсь). В Unicode ∘ — это
символ U+2218 RING OPERATOR. Кстати, в Python 3.0 станут возможными
идентификаторы Unicode.</p>

<p>А это простой тест модуля. Вначале получаем функцию <code>hex_square</code>,
которая является композицией <code>hex</code> и <code>sqr</code>:</p>

<pre><code>if __name__ == '__main__':
    hex_square = o(hex, sqr)
</code></pre>

<p>Затем красиво печатаем список квадратов первых 30 числел ≥ 0:</p>

<pre><code>    from pprint import pprint
    pprint(list(hex_square(x) for x in xrange(30)))
</code></pre>

<p>На этом пример заканчивается.</p></div>

В общем, всё просто: нужно только быть знакомым с make и sed. Зато теперь можно одновременно писать заметку в блог с кодом программы и проверять как она выполняется.

Реклама

Written by vlan

2008-05-18 в 22:17

Опубликовано в Uncategorized

Tagged with , , , , , , ,

комментариев 5

Subscribe to comments with RSS.

  1. Вы ошибаетесь, если думаете что «literate programming» — это просто программа с комментариями плюс простая utility чтобы выбрать из неё строчки-код или отформатировать все это как ХТМЛ.

    Главная идея Кнута в другом. Файл вообще без комментариев (хотя это непично) может быть a literate program, и наоборот, файл с морем комментариев может не быть a literate program.

    Идея же — в письме программы НА ПСЕВДОКОДЕ, который вы выдумываете на ходу и на ЧЕЛОВЕЧЕСКОМ языке.
    Операторы этого псевдокода становятся точными МАКРО, которые раскроются и подставятся.

    Но и это не все, потому что вторая важная идея — возможность писать в порядке, удобном для мышления и выдумывания, избавившись от порядка, предписанного языком инструкций для машины.

    Пример можно посмотреть здесь:
    http://community.livejournal.com/ru_perl/249441.html

    Да, третье: давно уже существуют общие простые программы, которые обеспечивают literate programming на любом языке.
    Можете написать такой скриптик на Питоне (и положить его на sourceforge), я писал свои на пёрле.

    anonym_mouse

    2008-05-20 at 03:03

  2. @anonym_mouse: Спасибо за комментарий и ссылку.

    Конечно, оригинальная концепция намного шире, чем просто выдирание комментариев из кода. Я знаком с WEB и FunnelWeb. Конечно, возможность писать код в порядке изложения текста замечательна. И в Haskell это возможно на уровне языка. Но для языков с последовательным выполнением инструкций, таких как Python, такой стиль документации небольшим скриптом, конечно, не сделаешь. Тем не менее при нормальной модульности кода вещи, о которых нужно говорить в документации, уже имеют своё имя, будь то вычисления или данные.

    Я же хотел получить практичное, хотя и очень ограниченное средство написания заметок в блоге с кодом. Думаю, две строчки в makefile — достаточно мало, чтобы позволить себе «запрограммировать» такую функциональность :)

    Да, я посмотрел в Вебе разные программы: и общие, и для Python, но ничего не приглянулось. Многие из них настаивают на языке форматирования доков, многие не достаточно простые по задумке.

    vlasovskikh

    2008-05-20 at 15:33

  3. Нет ничего проще noweb.

    Вы пишете свой html файл, но код помещаете в

    <<кусок кода>>=

    код

    код

    @

    и пишете дальше

    Куски могут быть в произвольном порядке и включать ссылки друг на друга (те же угловые скобки, но БЕЗ знака равно)

    Вот и все. Я использую noweb с perl’ом и lisp’ом. Мейкфайл в моем случае также состоит из 2х строчек. Одна ссылается на noweave, вторая на notangle. Для красоты я в noweave вставляю post-processing фильт на перле еще из 3х строчек.

    Все-таки какая-то тайна здесь скрыта. Все это так просто — и вместе с тем мало кто понимает принцип — программирования фразами на человеческом языке, которые могут выстраивать произвольно большие иерархии концепций

    anonym_mouse2

    2008-05-20 at 19:05

  4. Оригинальное литературное программирование Кнут реализовал вовсе не для С, а для Паскаля — TeX и METAFONT написаны на Pascal. Это уже потом — для С и всего остального.

    zahardzhan

    2010-09-27 at 12:03

    • Рекомендую глянуть в сети 3 книги Кнута «TeX the program», «METAFONT the program» и «MMIXware» — большие литературные программы, первые две на паскале (WEB), последняя — С (СWEB). Шедевры программной документации.

      Я для литературных программ для блога, для статей в блог без программ, и для просто программ, туду листов и вообще для много чего использую Emacs Org Mode, по сути это такой «офис для гиков».

      zahardzhan

      2010-09-27 at 12:15


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

Заполните поля или щелкните по значку, чтобы оставить свой комментарий:

Логотип WordPress.com

Для комментария используется ваша учётная запись WordPress.com. Выход / Изменить )

Фотография Twitter

Для комментария используется ваша учётная запись Twitter. Выход / Изменить )

Фотография Facebook

Для комментария используется ваша учётная запись Facebook. Выход / Изменить )

Google+ photo

Для комментария используется ваша учётная запись Google+. Выход / Изменить )

Connecting to %s

%d такие блоггеры, как: