OCaml

Поделись знанием:
Перейти к: навигация, поиск
Objective Caml
Семантика:

мультипарадигменный: функциональный, объектно-ориентированный, императивный

Автор:

INRIA

Система типов:

строгая, статическая

Диалекты:

F#, JoCaml, MetaOCaml, OcamlP3l

Испытал влияние:

Standard ML, Caml Light

Лицензия:

LGPL

Сайт:

[ocaml.org rg]

OCaml (Objective Caml) — современный объектно-ориентированный язык функционального программирования общего назначения, который был разработан с учётом безопасности исполнения и надёжности программ. Этот язык имеет высокую степень выразительности, что позволяет его легко выучить и использовать. Язык CaML поддерживает функциональную, императивную и объектно-ориентированную парадигмы программирования. Был разработан в 1985 году во французском институте INRIA, который занимается исследованиями в области информатики. Самый распространённый в практической работе диалект языка ML.

Инструментарий OCaml включает в себя интерпретатор, компилятор в байткод и оптимизирующий компилятор в машинный код, сравнимый по эффективности с Java и лишь немного уступающий по быстродействию C и C++[1].

На языке OCaml, в частности, написан рендеринг формул Википедии, использующих тег <math>, файлообменный клиент MLDonkey, стек управления гипервизором Xen xapi (является частью Xen Server/Xen Cloud Platform), язык программирования HaXe.





О языке

Место и роль в информатике

Язык OCaml является языком программирования общего назначения, но при этом имеет свои сложившиеся области применения[2].

Во-первых, это — создание «безопасных» (не только в смысле информационной безопасности) приложений. В языке используется сборка мусора, а большинство типов данных поставлено в рамки (англ. boxed), что означает предотвращение переполнения буферов во время исполнения программы. Кроме того, статическая типизация и проверки времени компиляции делают невозможными некоторые другие классы ошибок, такие как ошибки приведения типов, в силу отсутствия автоматического приведения типов. Кроме того, код может быть формально верифицирован. Имеются утилиты автоматического доказательства типовой корректности кода, превосходящие таковые для большинства языков программирования. И, что немаловажно, меры безопасности не влияют на эффективность исполняемого кода[2].

Другой областью успешного применения OCaml являются приложения, управляемые данными (data-driven). К этой области относится обработка текста, а также написание компиляторов. OCaml имеет не только средства для текстовой обработки (какими славится, например, Perl или AWK), но и инструменты для глубокого семантического анализа и преобразования текста, что делает OCaml применимым в задачах интеллектуального анализа данных (англ. data mining)[2].

Разумеется, OCaml, как и другие диалекты ML, используются в исследовательских задачах и задачах верификации, при котором основной код пишется на некотором языке программирования, а затем формально верифицируется и анализируется программой на OCaml[2]. Например, на OCaml написана система интерактивного доказательства теорем Coq.

Основные свойства

OCaml занимает особое место среди языков программирования благодаря сочетанию эффективности, выразительности и практичности. Среди особенностей языка, развивавшихся в течение более чем 40 лет, со времени создания ML, можно выделить[3]:

История

OCaml ведёт своё происхождение от ML (англ. meta language), который был реализован на диалекте Лиспа Робином Милнером в 1972 году в качестве программного средства для доказательства теорем, как метаязык логики вычислимых функций (LCF, англ. logic for computable functions). Позднее был сделан компилятор, а к 1980 году ML стал полноценной системой программирования[4].

Ги Кузино (Guy Cousineau) добавил в язык алгебраические типы данных и сопоставление с образцом и определил ML в виде категориальной абстрактной машины (CAM). Таким образом, CAM-ML мог быть описан, верифицирован и оптимизирован, что явилось шагом вперёд для ML[5].

Дальнейшим развитием был созданный к 1987 году Аскандером Суарецом (Ascánder Suárez) и продолженный Пьером Вейсом (Pierre Weis) и Мичелом Мони (Michel Mauny) язык Caml (переигранное CAM-ML)[4][5].

В 1990 году Ксавье Лерой (Xavier Leroy) и Дамьен Догигез (Damien Doligez) выпустили новую реализацию, названную Caml Light. В этой реализации на Си использовался интерпретатор байт-кода и быстрый сборщик мусора. С написанием библиотек, язык стал использоваться в образовании и исследовательских институтах[4][5].

В 1995 году увидел свет Caml Special Light, развиваемый К. Лероем. Система программирования получила компилятор в машинные коды, что поставило эффективность исполняемого кода в один ряд с другими компилируемыми языками. В то же время была разработана система модулей, идея которой была заимствована из Standard ML[4].

В современном виде OCaml появился в 1996 году, когда Дидье Реми (Didier Rémy) и Джером Вуйон (Jérôme Vouillon) реализовали для языка стройную и эффективную поддержку объектов. Эта объектная система позволяет на этапе компиляции в типобезопасной манере использовать идиомы объектно-ориентированного программирования, без свойственным C++ и Java проверок времени выполнения[4].

В 2000-х годах язык плавно развивался, одновременно получая всё большее признание в коммерческих проектах и образовании. Среди разработанного в это время можно отметить полиморфные методы и вариантный типы, именованные и необязательные параметры, модули первого класса, обобщённые алгебраические типы данных (GADT). Язык стал поддерживать несколько аппаратных платформ (X86, ARM, SPARC, PowerPC)[4][5].

Базовая семантика

Модель вычислений OCaml как языка функционального программирования строится на трёх основных конструкциях лямбда-исчисления: переменных[⇨], определениях функций[⇨] и применении функции к аргументам[6].

Переменные

Переменная — идентификатор, значение которого связано с определённой величиной. Имена переменных начинаются со строчной буквы или подчёркивания. Привязка обычно выполняется с помощью ключевого слова let, как в следующем примере в интерактивной оболочке[7]:

let v = 1;;

Переменные имеют область видимости. Например, в интерактивной оболочке переменную можно использовать в следующих за её привязкой командах. Аналогично, переменную, определённую в модуле, можно использовать после определения в данном модуле[7].

Привязка переменной может быть осуществлена и в области видимости, заданной конструкцией let-in, как в следующем примере по вычислению площади круга по радиусу:

# let area radius =
      let pi = 3.14 in
      radius *. radius *. pi ;;
val area : float -> float = <fun>
# area 2.0 ;;
- : float = 12.56

В OCaml привязки переменных являются неизменяемыми (как в математических уравнениях), то есть, значение переменной «присваивается» только один раз (единичное присваивание). Другое дело, что внутри let-in может быть другой let-in, в котором вводится другая переменная, которая может «затенить» первую[7].

Функции

Для определения функций в OCaml есть несколько синтаксических конструкций.

Функции можно определить с помощью ключевого слова function. Выражение для функции выглядит следующим образом[8]:

function x -> x + 1

В данном случае функция анонимная, и её можно использовать в качестве параметров других функций или применить к некоторому аргументу, например:

(function x -> x + 1) 5

Типом этой функции является int -> int, то есть, функция принимает целое и возвращает целое.

Функция может иметь несколько аргументов[9]:

function (x, y) -> x - y

В этом примере её тип: int * int -> int, то есть, на входе функции — пара[⇨], а на выходе — целое.

Есть и другой подход представления функций нескольких аргументов — преобразование N-арной функции в N функций одного аргумента — каррирование. Следующие два вида записи функции, вычисляющей произведение целочисленных аргументов, эквивалентны[9]:

function x -> function y -> x * y
fun x y -> x * y

Именованные функции можно получить, связав переменную с функцией[8]. Определение именованной функции настолько частая операция, что имеет отдельную синтаксическую поддержку. Следующие три записи — эквивалентные способы определить функцию (в интерактивной оболочке):

# let prod = function x -> function y -> x * y ;;
val prod : int -> int -> int = <fun>
# let prod x y = x * y ;;
val prod : int -> int -> int = <fun>
# let prod = fun x y -> x * y ;;
val prod : int -> int -> int = <fun>

Функции двух аргументов можно определить для использования инфиксной записи[8]:

# let (^^) x y = x**2.0 +. y**2.0 ;;
val ( ^^ ) : float -> float -> float = <fun>
# 2.0 ^^ 3.0 ;;
- : float = 13.
# (^^) 2.0 3.0 ;;
- : float = 13.

В этом примере определена функция (^^), вычисляющая сумму квадратов двух чисел с плавающей запятой. Последние два вида записи эквивалентны.

Рекурсивные функции, то есть функции, ссылающиеся на своё же определение, можно задать с помощью let rec[8]:

# let rec fac n =
    match n with 
    | 0 -> 1
    | x -> x * fac (x - 1)
  ;;

В этом же примере вычисления факториала применено сопоставление с образцом (конструкция match-with).

Аргументы функции можно определить как именованные. Именованные аргументы можно указывать в любом порядке[8]:

# let divmod ~x ~y = (x / y, x mod y) ;;
val divmod : x:int -> y:int -> int * int = <fun>
# divmod ~x:4 ~y:3 ;;
- : int * int = (1, 1)
# divmod ~y:3 ~x:4 ;;
- : int * int = (1, 1)

В OCaml можно опускать значения, используя уплотнённую запись (англ. label punning), если имя параметра и переменной совпадают[8]:

# let x = 4 in
  let y = 3 in
  divmod x y ;;
- : int * int = (1, 1)

Выражения

Ассоциативность операций в выражениях OCaml определяется префиксом, распространяясь таким образом на операции, определённые пользователем. Знак - работает как префиксная, так и инфиксная операция, причём при необходимости использовать в качестве префикса совместно с применением функции, параметр нужно заключить в скобки[10].

Префикс операции Ассоциативность
! ? ~ Префикс
. .( .[ .{
применение функции, конструктора, метки, assert, lazy Левая
- -. Префикс
** lsl lsr asr Правая
* / % mod land lor lxor Левая
+ - Левая
:: Правая
@ ^ Правая
& $ != Левая
& && Правая
or || Правая
,
<- := Правая
if
; Правая
let match fun function try

Система типов

Примитивные типы

Язык OCaml имеет несколько примитивных типов: числовые типы (целый и числа с плавающей запятой), символьный, строки символов, булевский[11].

Целый тип представляет целые числа из интервала [−230, 230 − 1] и [−262, 262 − 1] для 32- и 64-битных архитектур соответственно. С целыми числами можно производить обычные операции сложения, вычитания, умножения, деления, взятия остатка от деления: +, -, *, /, mod. В случае выхода результата за допустимый интервал ошибки не происходит, а результат вычисляется по модулю границы интервала[12].

Числа с плавающей запятой представляются 53-битной мантиссой и порядком из интервала [−1022, 1023], следуя стандарту IEEE 754 для чисел с двойной точностью. В операциях эти числа нельзя смешивать с целыми. Кроме того, операции над числами с плавающей запятой синтаксически отличаются от целочисленных операций: +., -., *., /.. Также имеется операция возведения в степень: **. Для преобразования целых чисел в числа с плавающей запятой и обратно доступны функции: float_of_int и int_of_float[12].

Для чисел с плавающей запятой имеются и другие математические функции: тригонометрические (sin, cos, tan, asin, acos, atan), округления (ceil, floor), экспоненциальная (exp), логарифмические (log, log10), а также извлечение квадратного корня (sqrt)[12]. Для числовых типов имеются и полиморфные операции сравнения[12].

Символьный тип — char — соответствует представлению символа с кодом от 0 до 255 (первые 128 символов совпадают с ASCII). Строчный тип — string — последовательность символов (максимальная длина: 224 — 6)[13]. Пример с использованием функции преобразования целого к строке и операции конкатенации:

# "Example " ^ string_of_int(2) ;;
- : string = "Example 2"

Булевский тип имеет два значения: true (истина) и false (ложь). Операции над величинами булевского типа: унарная not (отрицание), бинарные: && (и), || (или). Бинарные операции вычисляют сначала левый аргумент, а правый — только если требуется[14].

Булевские значения получаются в результате сравнений: = (структурное равенство), == (тождество), <> (отрицание структурного равенства), != (отрицание тождества), <, >, <=, >=. Для примитивных типов кроме строк и чисел с плавающей точкой структурное равенство и тождество совпадают, для других типов тождественными считаются значения, располагающиеся по одному адресу в памяти, а при структурном сравнении значения проверяются по-компонентно[14].

Кроме того, а OCaml имеется специальный тип unit, который имеет всего одно значение — ()[14].

Списки

В OCaml список — конечная неизменяемая последовательность элементов одного типа, реализованная как односвязный список. Следующий пример демонстрирует синтаксис списка[15]:

# ['a'; 'b'; 'c'] ;;
- : char list = ['a'; 'b'; 'c']
# 'a' :: ('b' :: ('c' :: [])) ;;
- : char list = ['a'; 'b'; 'c']
# 'a' :: 'b' :: 'c' :: [] ;;
- : char list = ['a'; 'b'; 'c']
# [] ;;
- : 'a list = []

Операция :: позволяет добавлять построить список на основе нового элемента и хвоста старого списка. При этом «старый» список не изменяется:

# let lst = [1; 2] ;;
val lst : int list = [1; 2]
# let lst1 = 0 :: lst ;;
val lst1 : int list = [0; 1; 2]
# lst ;;
- : int list = [1; 2]
# lst1 ;;
- : int list = [0; 1; 2]
Пример: вычисление суммы элементов списка

Список является одним из основных типов данных в OCaml. Следующий пример кода определяет рекурсивную (обратите внимание на ключевое слово rec) функцию, которая перебирает элементы данного списка и возвращает их сумму.

let rec sum xs =
  match xs with
    | []       -> 0
    | x :: xs' -> x + sum xs'
 # sum [1;2;3;4;5];;
 - : int = 15

Другой способ подсчёта суммы заключается в использовании функции свёртки:

let sum xs =
    List.fold_left (+) 0 xs

  # sum [1;2;3;4;5];;
  - : int = 15

Записи

Записи являются важным элементом в системе типов OCaml. Запись представляет собой набор хранимых вместе значений, при котором каждый элемент значения-записи доступен по своему имени — имени поля записи. Пример описания типа, связывания записи с переменной и доступ к полю записи[16]:

# type user =
    { login       : string;
      password    : string;
      nick        : string;
    };;
# let usr = { login = "myuser"; password = "secret"; nick = "aka" ; } ;;
val usr : user = {login = "myuser"; password = "secret"; nick = "aka"}
# usr.nick ;;
- : string = "aka"

Следует заметить, что тип переменной usr был установлен компилятором автоматически.

Как и в случае с другими типами, тип может быть параметризован. Другие возможности записей[16]:

  • сопоставление с образцом (irrefutable)
  • синтаксические уплотнение полей (field punning) записи в случае совпадения имён полей и переменных
  • повторное использование полей и разрешение неоднозначности с помощью модулей
  • функциональное обновление (functional update) записи
  • изменяемые (mutable) поля
  • fieldslib и поле записи как объект первого класса
  • итераторы полей

Вариантный тип

Вариантный тип представляет данные, которые могут принимать различные формы, определяемые явно заданными метками. В следующем примере определён тип для базовых цветов[17]:

# type main_color = Red | Green | Blue ;;
# Blue ;; 
- : main_color = Blue
# (Red, Blue) ;;
- : main_color * main_color = (Red, Blue)

В примере выше вариантный тип используется в качестве перечислимого типа. В OCaml вариантный тип, тем не менее, является более богатым, так как помимо меток позволяет задавать и данные, например:

# type color_scheme = RGB of int * int * int | CMYK of float * float * float * float;;
type color_scheme =
    RGB of int * int * int
  | CMYK of float * float * float * float

При определении функций вариантный тип естественно сочетается с сопоставлением с образцом.

Объекты

В OCaml объекты и их типы полностью отделены от системы классов. Классы используются для построения объектов и поддержки наследования, но не являются типами объектов. Объекты имеют собственные объектные типы (object types), и для работы с объектами классы применять необязательно. Объекты не так часто используются в OCaml (так, система модулей является более выразительной, чем объекты, так как модули могут включать типы, а классы и объекты — нет). Основным преимуществом объектов перед записями — они не требуют объявления типов и обладают большей гибкостью благодаря полиморфизму строчных переменных (англ. row polymorphism). С другой стороны, преимущества объектов проявляются при использовании системы классов. В отличие от модулей, классы поддерживают позднее связывание, что позволяется ссылаться на методы объекта без статически заданной реализации и использовать открытую рекурсию (в случае с модулями можно использовать функции и функторы, но синтаксически такие описания требуют написания большего количества кода)[18].

Вывод типов

Хотя OCaml является языком программирования с сильной типизацией, система вывода типов (англ. type inference) позволяет определять тип выражения на основе имеющейся информации о его компонентах. В следующем примере функции проверки числа на чётность не указано ни одной декларации типа, и тем не менее у компилятора языка есть полная информация о типе функции[19]:

# let odd x = x mod 2 <> 0 ;;
val odd : int -> bool = <fun>

Императивное программирование и функции с побочными эффектами

Хотя бо́льшая часть кода может быть выполнена на OCaml в чистом функциональном стиле, язык позволяет программировать императивно, используя побочные эффекты, а также алгоритмические конструкции вроде циклов[20].

Следующий пример напечатает на стандартном выводе (это — побочный эффект функции printf) 11 строк:

for i = 0 to 10 do 
  Printf.printf "i =%d\n" i
done;;

В следующем (довольно искусственном) примере элементы массива на месте увеличиваются на единицу в цикле с предусловием. Для индекса массива используется ссылка (ref), которая инкрементируется в теле цикла:

# let incr_ar ar =
    let i = ref 0 in
    while !i < Array.length ar do
      ar.(!i) <- ar.(!i) + 1;
      incr i
  done ;;
val incr_ar : int array -> unit = <fun>
# let nums = [|1;2;3;4;5|];;
val nums : int array = [|1; 2; 3; 4; 5|]
# incr_ar nums;;
- : unit = ()
# nums;;
- : int array = [|2; 3; 4; 5; 6|]

Хотя результатов вычислений можно достичь и чисто функциональными средствами, побочные эффекты позволяют оптимизировать вычисления. Например, они позволяются организовать ленивые вычисления и мемоизацию[20].

Крупномасштабное программирование

Модульность

OCaml можно представить себе как состоящий из двух языков: язык ядра со значениями и типами и язык модулей и их сигнатур. Эти языки образуют два слоя в том смысле, что модули могут содержать типы и значения, а обычные значения не могут содержать модулей и модулей-типов. Тем не менее, OCaml предлагает механизм модулей первого класса, которые могут быть значениями и при необходимости преобразуются в обычные модули и обратно[21].

Функторы

Система модулей OCaml не ограничивается модульной организацией кода и интерфейсами. Одним из важных инструментов обобщённого программирования являются функторы. Упрощённо говоря, функторы являются функцией из модуля в модули, что позволяет реализовать следующие механизмы[22]:

Примеры программ

Запуск интерпретатора OCaml

Для запуска интерпретатора языка OCaml необходимо в консоли ввести следующую команду:

$ ocaml
       Objective Caml version 3.09.0
#

Теперь можно вводить различные выражения, которые интерпретатор будет считывать, вычислять и выводить результат на экран:

# 1 + 2 * 3;;
- : int = 7

Hello world

Следующая программа «hello.ml»:

print_endline "Hello World!";;

может быть скомпилирована либо в байт-код:

$ ocamlc hello.ml -o hello

либо в оптимизированный машинный код:

$ ocamlopt hello.ml -o hello

и запущена:

$ ./hello
Hello World!
$

Быстрая сортировка

В следующем примере приведен алгоритм быстрой сортировки, который сортирует список в порядке возрастания:

 let rec qsort = function
   | [] -> []
   | pivot :: rest ->
       let is_less x = x < pivot in
       let left, right = List.partition is_less rest in
       qsort left @ [pivot] @ qsort right

Последовательность Фибоначчи

let rec fib_aux n a b =
  match n with
  | 0 -> a
  | _ -> fib_aux (n - 1) (a + b) a
let fib n = fib_aux n 0 1

См. также

Напишите отзыв о статье "OCaml"

Примечания

Литература

[www.ocaml-lang.org/books.html Список книг, доступных онлайн]
  • Minsky, Y. and Madhavapeddy, A. and Hickey, J. Real World OCaml: Functional Programming for the Masses. — O'Reilly Media, 2013. — 510 p. — ISBN 9781449324766.
    • Перевод на русский язык: Мински, Ярон; Мадхавапедди, Анил; Хикки, Джейсон. Программирование на языке OCaml = Real World OCaml: Functional Programming for the Masses. — ДМК, 2014. — 536 с. — (Функциональное программирование). — ISBN 978-5-97060-102-0.
  • Joshua B. Smith. Practical OCaml. — Apress, 2006. — 488 с. — ISBN 9781590596203.
  • Yaron Minsky [queue.acm.org/detail.cfm?id=2038036 OCaml for the Masses] // ACM Queue: Programming Languages. — 2011. — Т. 9, № 9.
  • Chailloux, Manoury, Pagano. [bookre.org/reader?file=1251401 Developing Applications With Objective Caml]. — 2007.
  • Харрисон Дж. [dspace.nsu.ru:8080/jspui/bitstream/nsu/88/1/Harrison.pdf Введение в Функциональное Программирование] = www.cl.cam.ac.uk/Teaching/Lectures/funprog-jrh-1996/. — 1997.

Ссылки

  • [caml.inria.fr/ Официальный сайт языка OCaml] (англ.)
  • [www.ocamlcore.org/ Сайт OCaml Community] (англ.)
  • [www.camlcity.org/ Сайт Gerd Stolpmann’a, посвящённый OCaml] (англ.)
  • [ocaml.spb.ru/ Перевод документации на русский язык]
  • [shamil.free.fr/comp/ocaml/ Перевод на русский язык книги O’Reilly DAOC]
  • Emmanuel Chailloux, Pascal Manoury and Bruno Pagano [caml.inria.fr/pub/docs/oreilly-book/ Developing Applications With Objective Caml] (англ.)
  1. [www.itu.dk/courses/BPRD/E2009/fundamental-1967.pdf C. Strachey — Fundamental Concepts in Programming Languages]
  2. Rossberg A. [objectmix.com/302412-functors-runtime-vs-compile-time.html Functors and runtime vs compile time].

Отрывок, характеризующий OCaml

– Ну, батюшка Михайло Митрич, – обратился он к одному батальонному командиру (батальонный командир улыбаясь подался вперед; видно было, что они были счастливы), – досталось на орехи нынче ночью. Однако, кажется, ничего, полк не из дурных… А?
Батальонный командир понял веселую иронию и засмеялся.
– И на Царицыном лугу с поля бы не прогнали.
– Что? – сказал командир.
В это время по дороге из города, по которой расставлены были махальные, показались два верховые. Это были адъютант и казак, ехавший сзади.
Адъютант был прислан из главного штаба подтвердить полковому командиру то, что было сказано неясно во вчерашнем приказе, а именно то, что главнокомандующий желал видеть полк совершенно в том положении, в котором oн шел – в шинелях, в чехлах и без всяких приготовлений.
К Кутузову накануне прибыл член гофкригсрата из Вены, с предложениями и требованиями итти как можно скорее на соединение с армией эрцгерцога Фердинанда и Мака, и Кутузов, не считая выгодным это соединение, в числе прочих доказательств в пользу своего мнения намеревался показать австрийскому генералу то печальное положение, в котором приходили войска из России. С этою целью он и хотел выехать навстречу полку, так что, чем хуже было бы положение полка, тем приятнее было бы это главнокомандующему. Хотя адъютант и не знал этих подробностей, однако он передал полковому командиру непременное требование главнокомандующего, чтобы люди были в шинелях и чехлах, и что в противном случае главнокомандующий будет недоволен. Выслушав эти слова, полковой командир опустил голову, молча вздернул плечами и сангвиническим жестом развел руки.
– Наделали дела! – проговорил он. – Вот я вам говорил же, Михайло Митрич, что на походе, так в шинелях, – обратился он с упреком к батальонному командиру. – Ах, мой Бог! – прибавил он и решительно выступил вперед. – Господа ротные командиры! – крикнул он голосом, привычным к команде. – Фельдфебелей!… Скоро ли пожалуют? – обратился он к приехавшему адъютанту с выражением почтительной учтивости, видимо относившейся к лицу, про которое он говорил.
– Через час, я думаю.
– Успеем переодеть?
– Не знаю, генерал…
Полковой командир, сам подойдя к рядам, распорядился переодеванием опять в шинели. Ротные командиры разбежались по ротам, фельдфебели засуетились (шинели были не совсем исправны) и в то же мгновение заколыхались, растянулись и говором загудели прежде правильные, молчаливые четвероугольники. Со всех сторон отбегали и подбегали солдаты, подкидывали сзади плечом, через голову перетаскивали ранцы, снимали шинели и, высоко поднимая руки, натягивали их в рукава.
Через полчаса всё опять пришло в прежний порядок, только четвероугольники сделались серыми из черных. Полковой командир, опять подрагивающею походкой, вышел вперед полка и издалека оглядел его.
– Это что еще? Это что! – прокричал он, останавливаясь. – Командира 3 й роты!..
– Командир 3 й роты к генералу! командира к генералу, 3 й роты к командиру!… – послышались голоса по рядам, и адъютант побежал отыскивать замешкавшегося офицера.
Когда звуки усердных голосов, перевирая, крича уже «генерала в 3 ю роту», дошли по назначению, требуемый офицер показался из за роты и, хотя человек уже пожилой и не имевший привычки бегать, неловко цепляясь носками, рысью направился к генералу. Лицо капитана выражало беспокойство школьника, которому велят сказать невыученный им урок. На красном (очевидно от невоздержания) носу выступали пятна, и рот не находил положения. Полковой командир с ног до головы осматривал капитана, в то время как он запыхавшись подходил, по мере приближения сдерживая шаг.
– Вы скоро людей в сарафаны нарядите! Это что? – крикнул полковой командир, выдвигая нижнюю челюсть и указывая в рядах 3 й роты на солдата в шинели цвета фабричного сукна, отличавшегося от других шинелей. – Сами где находились? Ожидается главнокомандующий, а вы отходите от своего места? А?… Я вас научу, как на смотр людей в казакины одевать!… А?…
Ротный командир, не спуская глаз с начальника, всё больше и больше прижимал свои два пальца к козырьку, как будто в одном этом прижимании он видел теперь свое спасенье.
– Ну, что ж вы молчите? Кто у вас там в венгерца наряжен? – строго шутил полковой командир.
– Ваше превосходительство…
– Ну что «ваше превосходительство»? Ваше превосходительство! Ваше превосходительство! А что ваше превосходительство – никому неизвестно.
– Ваше превосходительство, это Долохов, разжалованный… – сказал тихо капитан.
– Что он в фельдмаршалы, что ли, разжалован или в солдаты? А солдат, так должен быть одет, как все, по форме.
– Ваше превосходительство, вы сами разрешили ему походом.
– Разрешил? Разрешил? Вот вы всегда так, молодые люди, – сказал полковой командир, остывая несколько. – Разрешил? Вам что нибудь скажешь, а вы и… – Полковой командир помолчал. – Вам что нибудь скажешь, а вы и… – Что? – сказал он, снова раздражаясь. – Извольте одеть людей прилично…
И полковой командир, оглядываясь на адъютанта, своею вздрагивающею походкой направился к полку. Видно было, что его раздражение ему самому понравилось, и что он, пройдясь по полку, хотел найти еще предлог своему гневу. Оборвав одного офицера за невычищенный знак, другого за неправильность ряда, он подошел к 3 й роте.
– Кааак стоишь? Где нога? Нога где? – закричал полковой командир с выражением страдания в голосе, еще человек за пять не доходя до Долохова, одетого в синеватую шинель.
Долохов медленно выпрямил согнутую ногу и прямо, своим светлым и наглым взглядом, посмотрел в лицо генерала.
– Зачем синяя шинель? Долой… Фельдфебель! Переодеть его… дря… – Он не успел договорить.
– Генерал, я обязан исполнять приказания, но не обязан переносить… – поспешно сказал Долохов.
– Во фронте не разговаривать!… Не разговаривать, не разговаривать!…
– Не обязан переносить оскорбления, – громко, звучно договорил Долохов.
Глаза генерала и солдата встретились. Генерал замолчал, сердито оттягивая книзу тугой шарф.
– Извольте переодеться, прошу вас, – сказал он, отходя.


– Едет! – закричал в это время махальный.
Полковой командир, покраснел, подбежал к лошади, дрожащими руками взялся за стремя, перекинул тело, оправился, вынул шпагу и с счастливым, решительным лицом, набок раскрыв рот, приготовился крикнуть. Полк встрепенулся, как оправляющаяся птица, и замер.
– Смир р р р на! – закричал полковой командир потрясающим душу голосом, радостным для себя, строгим в отношении к полку и приветливым в отношении к подъезжающему начальнику.
По широкой, обсаженной деревьями, большой, бесшоссейной дороге, слегка погромыхивая рессорами, шибкою рысью ехала высокая голубая венская коляска цугом. За коляской скакали свита и конвой кроатов. Подле Кутузова сидел австрийский генерал в странном, среди черных русских, белом мундире. Коляска остановилась у полка. Кутузов и австрийский генерал о чем то тихо говорили, и Кутузов слегка улыбнулся, в то время как, тяжело ступая, он опускал ногу с подножки, точно как будто и не было этих 2 000 людей, которые не дыша смотрели на него и на полкового командира.
Раздался крик команды, опять полк звеня дрогнул, сделав на караул. В мертвой тишине послышался слабый голос главнокомандующего. Полк рявкнул: «Здравья желаем, ваше го го го го ство!» И опять всё замерло. Сначала Кутузов стоял на одном месте, пока полк двигался; потом Кутузов рядом с белым генералом, пешком, сопутствуемый свитою, стал ходить по рядам.
По тому, как полковой командир салютовал главнокомандующему, впиваясь в него глазами, вытягиваясь и подбираясь, как наклоненный вперед ходил за генералами по рядам, едва удерживая подрагивающее движение, как подскакивал при каждом слове и движении главнокомандующего, – видно было, что он исполнял свои обязанности подчиненного еще с большим наслаждением, чем обязанности начальника. Полк, благодаря строгости и старательности полкового командира, был в прекрасном состоянии сравнительно с другими, приходившими в то же время к Браунау. Отсталых и больных было только 217 человек. И всё было исправно, кроме обуви.
Кутузов прошел по рядам, изредка останавливаясь и говоря по нескольку ласковых слов офицерам, которых он знал по турецкой войне, а иногда и солдатам. Поглядывая на обувь, он несколько раз грустно покачивал головой и указывал на нее австрийскому генералу с таким выражением, что как бы не упрекал в этом никого, но не мог не видеть, как это плохо. Полковой командир каждый раз при этом забегал вперед, боясь упустить слово главнокомандующего касательно полка. Сзади Кутузова, в таком расстоянии, что всякое слабо произнесенное слово могло быть услышано, шло человек 20 свиты. Господа свиты разговаривали между собой и иногда смеялись. Ближе всех за главнокомандующим шел красивый адъютант. Это был князь Болконский. Рядом с ним шел его товарищ Несвицкий, высокий штаб офицер, чрезвычайно толстый, с добрым, и улыбающимся красивым лицом и влажными глазами; Несвицкий едва удерживался от смеха, возбуждаемого черноватым гусарским офицером, шедшим подле него. Гусарский офицер, не улыбаясь, не изменяя выражения остановившихся глаз, с серьезным лицом смотрел на спину полкового командира и передразнивал каждое его движение. Каждый раз, как полковой командир вздрагивал и нагибался вперед, точно так же, точь в точь так же, вздрагивал и нагибался вперед гусарский офицер. Несвицкий смеялся и толкал других, чтобы они смотрели на забавника.
Кутузов шел медленно и вяло мимо тысячей глаз, которые выкатывались из своих орбит, следя за начальником. Поровнявшись с 3 й ротой, он вдруг остановился. Свита, не предвидя этой остановки, невольно надвинулась на него.
– А, Тимохин! – сказал главнокомандующий, узнавая капитана с красным носом, пострадавшего за синюю шинель.
Казалось, нельзя было вытягиваться больше того, как вытягивался Тимохин, в то время как полковой командир делал ему замечание. Но в эту минуту обращения к нему главнокомандующего капитан вытянулся так, что, казалось, посмотри на него главнокомандующий еще несколько времени, капитан не выдержал бы; и потому Кутузов, видимо поняв его положение и желая, напротив, всякого добра капитану, поспешно отвернулся. По пухлому, изуродованному раной лицу Кутузова пробежала чуть заметная улыбка.
– Еще измайловский товарищ, – сказал он. – Храбрый офицер! Ты доволен им? – спросил Кутузов у полкового командира.
И полковой командир, отражаясь, как в зеркале, невидимо для себя, в гусарском офицере, вздрогнул, подошел вперед и отвечал:
– Очень доволен, ваше высокопревосходительство.
– Мы все не без слабостей, – сказал Кутузов, улыбаясь и отходя от него. – У него была приверженность к Бахусу.
Полковой командир испугался, не виноват ли он в этом, и ничего не ответил. Офицер в эту минуту заметил лицо капитана с красным носом и подтянутым животом и так похоже передразнил его лицо и позу, что Несвицкий не мог удержать смеха.
Кутузов обернулся. Видно было, что офицер мог управлять своим лицом, как хотел: в ту минуту, как Кутузов обернулся, офицер успел сделать гримасу, а вслед за тем принять самое серьезное, почтительное и невинное выражение.
Третья рота была последняя, и Кутузов задумался, видимо припоминая что то. Князь Андрей выступил из свиты и по французски тихо сказал:
– Вы приказали напомнить о разжалованном Долохове в этом полку.
– Где тут Долохов? – спросил Кутузов.
Долохов, уже переодетый в солдатскую серую шинель, не дожидался, чтоб его вызвали. Стройная фигура белокурого с ясными голубыми глазами солдата выступила из фронта. Он подошел к главнокомандующему и сделал на караул.
– Претензия? – нахмурившись слегка, спросил Кутузов.
– Это Долохов, – сказал князь Андрей.
– A! – сказал Кутузов. – Надеюсь, что этот урок тебя исправит, служи хорошенько. Государь милостив. И я не забуду тебя, ежели ты заслужишь.
Голубые ясные глаза смотрели на главнокомандующего так же дерзко, как и на полкового командира, как будто своим выражением разрывая завесу условности, отделявшую так далеко главнокомандующего от солдата.
– Об одном прошу, ваше высокопревосходительство, – сказал он своим звучным, твердым, неспешащим голосом. – Прошу дать мне случай загладить мою вину и доказать мою преданность государю императору и России.
Кутузов отвернулся. На лице его промелькнула та же улыбка глаз, как и в то время, когда он отвернулся от капитана Тимохина. Он отвернулся и поморщился, как будто хотел выразить этим, что всё, что ему сказал Долохов, и всё, что он мог сказать ему, он давно, давно знает, что всё это уже прискучило ему и что всё это совсем не то, что нужно. Он отвернулся и направился к коляске.
Полк разобрался ротами и направился к назначенным квартирам невдалеке от Браунау, где надеялся обуться, одеться и отдохнуть после трудных переходов.
– Вы на меня не претендуете, Прохор Игнатьич? – сказал полковой командир, объезжая двигавшуюся к месту 3 ю роту и подъезжая к шедшему впереди ее капитану Тимохину. Лицо полкового командира выражало после счастливо отбытого смотра неудержимую радость. – Служба царская… нельзя… другой раз во фронте оборвешь… Сам извинюсь первый, вы меня знаете… Очень благодарил! – И он протянул руку ротному.
– Помилуйте, генерал, да смею ли я! – отвечал капитан, краснея носом, улыбаясь и раскрывая улыбкой недостаток двух передних зубов, выбитых прикладом под Измаилом.
– Да господину Долохову передайте, что я его не забуду, чтоб он был спокоен. Да скажите, пожалуйста, я всё хотел спросить, что он, как себя ведет? И всё…
– По службе очень исправен, ваше превосходительство… но карахтер… – сказал Тимохин.
– А что, что характер? – спросил полковой командир.
– Находит, ваше превосходительство, днями, – говорил капитан, – то и умен, и учен, и добр. А то зверь. В Польше убил было жида, изволите знать…
– Ну да, ну да, – сказал полковой командир, – всё надо пожалеть молодого человека в несчастии. Ведь большие связи… Так вы того…
– Слушаю, ваше превосходительство, – сказал Тимохин, улыбкой давая чувствовать, что он понимает желания начальника.
– Ну да, ну да.
Полковой командир отыскал в рядах Долохова и придержал лошадь.
– До первого дела – эполеты, – сказал он ему.
Долохов оглянулся, ничего не сказал и не изменил выражения своего насмешливо улыбающегося рта.
– Ну, вот и хорошо, – продолжал полковой командир. – Людям по чарке водки от меня, – прибавил он, чтобы солдаты слышали. – Благодарю всех! Слава Богу! – И он, обогнав роту, подъехал к другой.
– Что ж, он, право, хороший человек; с ним служить можно, – сказал Тимохин субалтерн офицеру, шедшему подле него.
– Одно слово, червонный!… (полкового командира прозвали червонным королем) – смеясь, сказал субалтерн офицер.
Счастливое расположение духа начальства после смотра перешло и к солдатам. Рота шла весело. Со всех сторон переговаривались солдатские голоса.
– Как же сказывали, Кутузов кривой, об одном глазу?
– А то нет! Вовсе кривой.
– Не… брат, глазастее тебя. Сапоги и подвертки – всё оглядел…
– Как он, братец ты мой, глянет на ноги мне… ну! думаю…
– А другой то австрияк, с ним был, словно мелом вымазан. Как мука, белый. Я чай, как амуницию чистят!
– Что, Федешоу!… сказывал он, что ли, когда стражения начнутся, ты ближе стоял? Говорили всё, в Брунове сам Бунапарте стоит.
– Бунапарте стоит! ишь врет, дура! Чего не знает! Теперь пруссак бунтует. Австрияк его, значит, усмиряет. Как он замирится, тогда и с Бунапартом война откроется. А то, говорит, в Брунове Бунапарте стоит! То то и видно, что дурак. Ты слушай больше.
– Вишь черти квартирьеры! Пятая рота, гляди, уже в деревню заворачивает, они кашу сварят, а мы еще до места не дойдем.
– Дай сухарика то, чорт.
– А табаку то вчера дал? То то, брат. Ну, на, Бог с тобой.
– Хоть бы привал сделали, а то еще верст пять пропрем не емши.
– То то любо было, как немцы нам коляски подавали. Едешь, знай: важно!
– А здесь, братец, народ вовсе оголтелый пошел. Там всё как будто поляк был, всё русской короны; а нынче, брат, сплошной немец пошел.
– Песенники вперед! – послышался крик капитана.
И перед роту с разных рядов выбежало человек двадцать. Барабанщик запевало обернулся лицом к песенникам, и, махнув рукой, затянул протяжную солдатскую песню, начинавшуюся: «Не заря ли, солнышко занималося…» и кончавшуюся словами: «То то, братцы, будет слава нам с Каменскиим отцом…» Песня эта была сложена в Турции и пелась теперь в Австрии, только с тем изменением, что на место «Каменскиим отцом» вставляли слова: «Кутузовым отцом».
Оторвав по солдатски эти последние слова и махнув руками, как будто он бросал что то на землю, барабанщик, сухой и красивый солдат лет сорока, строго оглянул солдат песенников и зажмурился. Потом, убедившись, что все глаза устремлены на него, он как будто осторожно приподнял обеими руками какую то невидимую, драгоценную вещь над головой, подержал ее так несколько секунд и вдруг отчаянно бросил ее:
Ах, вы, сени мои, сени!
«Сени новые мои…», подхватили двадцать голосов, и ложечник, несмотря на тяжесть амуниции, резво выскочил вперед и пошел задом перед ротой, пошевеливая плечами и угрожая кому то ложками. Солдаты, в такт песни размахивая руками, шли просторным шагом, невольно попадая в ногу. Сзади роты послышались звуки колес, похрускиванье рессор и топот лошадей.
Кутузов со свитой возвращался в город. Главнокомандующий дал знак, чтобы люди продолжали итти вольно, и на его лице и на всех лицах его свиты выразилось удовольствие при звуках песни, при виде пляшущего солдата и весело и бойко идущих солдат роты. Во втором ряду, с правого фланга, с которого коляска обгоняла роты, невольно бросался в глаза голубоглазый солдат, Долохов, который особенно бойко и грациозно шел в такт песни и глядел на лица проезжающих с таким выражением, как будто он жалел всех, кто не шел в это время с ротой. Гусарский корнет из свиты Кутузова, передразнивавший полкового командира, отстал от коляски и подъехал к Долохову.
Гусарский корнет Жерков одно время в Петербурге принадлежал к тому буйному обществу, которым руководил Долохов. За границей Жерков встретил Долохова солдатом, но не счел нужным узнать его. Теперь, после разговора Кутузова с разжалованным, он с радостью старого друга обратился к нему:
– Друг сердечный, ты как? – сказал он при звуках песни, ровняя шаг своей лошади с шагом роты.
– Я как? – отвечал холодно Долохов, – как видишь.
Бойкая песня придавала особенное значение тону развязной веселости, с которой говорил Жерков, и умышленной холодности ответов Долохова.
– Ну, как ладишь с начальством? – спросил Жерков.
– Ничего, хорошие люди. Ты как в штаб затесался?
– Прикомандирован, дежурю.
Они помолчали.
«Выпускала сокола да из правого рукава», говорила песня, невольно возбуждая бодрое, веселое чувство. Разговор их, вероятно, был бы другой, ежели бы они говорили не при звуках песни.
– Что правда, австрийцев побили? – спросил Долохов.
– А чорт их знает, говорят.
– Я рад, – отвечал Долохов коротко и ясно, как того требовала песня.
– Что ж, приходи к нам когда вечерком, фараон заложишь, – сказал Жерков.
– Или у вас денег много завелось?
– Приходи.
– Нельзя. Зарок дал. Не пью и не играю, пока не произведут.
– Да что ж, до первого дела…
– Там видно будет.
Опять они помолчали.
– Ты заходи, коли что нужно, все в штабе помогут… – сказал Жерков.
Долохов усмехнулся.
– Ты лучше не беспокойся. Мне что нужно, я просить не стану, сам возьму.
– Да что ж, я так…
– Ну, и я так.
– Прощай.
– Будь здоров…
… и высоко, и далеко,
На родиму сторону…
Жерков тронул шпорами лошадь, которая раза три, горячась, перебила ногами, не зная, с какой начать, справилась и поскакала, обгоняя роту и догоняя коляску, тоже в такт песни.


Возвратившись со смотра, Кутузов, сопутствуемый австрийским генералом, прошел в свой кабинет и, кликнув адъютанта, приказал подать себе некоторые бумаги, относившиеся до состояния приходивших войск, и письма, полученные от эрцгерцога Фердинанда, начальствовавшего передовою армией. Князь Андрей Болконский с требуемыми бумагами вошел в кабинет главнокомандующего. Перед разложенным на столе планом сидели Кутузов и австрийский член гофкригсрата.
– А… – сказал Кутузов, оглядываясь на Болконского, как будто этим словом приглашая адъютанта подождать, и продолжал по французски начатый разговор.
– Я только говорю одно, генерал, – говорил Кутузов с приятным изяществом выражений и интонации, заставлявшим вслушиваться в каждое неторопливо сказанное слово. Видно было, что Кутузов и сам с удовольствием слушал себя. – Я только одно говорю, генерал, что ежели бы дело зависело от моего личного желания, то воля его величества императора Франца давно была бы исполнена. Я давно уже присоединился бы к эрцгерцогу. И верьте моей чести, что для меня лично передать высшее начальство армией более меня сведущему и искусному генералу, какими так обильна Австрия, и сложить с себя всю эту тяжкую ответственность для меня лично было бы отрадой. Но обстоятельства бывают сильнее нас, генерал.
И Кутузов улыбнулся с таким выражением, как будто он говорил: «Вы имеете полное право не верить мне, и даже мне совершенно всё равно, верите ли вы мне или нет, но вы не имеете повода сказать мне это. И в этом то всё дело».
Австрийский генерал имел недовольный вид, но не мог не в том же тоне отвечать Кутузову.
– Напротив, – сказал он ворчливым и сердитым тоном, так противоречившим лестному значению произносимых слов, – напротив, участие вашего превосходительства в общем деле высоко ценится его величеством; но мы полагаем, что настоящее замедление лишает славные русские войска и их главнокомандующих тех лавров, которые они привыкли пожинать в битвах, – закончил он видимо приготовленную фразу.
Кутузов поклонился, не изменяя улыбки.
– А я так убежден и, основываясь на последнем письме, которым почтил меня его высочество эрцгерцог Фердинанд, предполагаю, что австрийские войска, под начальством столь искусного помощника, каков генерал Мак, теперь уже одержали решительную победу и не нуждаются более в нашей помощи, – сказал Кутузов.
Генерал нахмурился. Хотя и не было положительных известий о поражении австрийцев, но было слишком много обстоятельств, подтверждавших общие невыгодные слухи; и потому предположение Кутузова о победе австрийцев было весьма похоже на насмешку. Но Кутузов кротко улыбался, всё с тем же выражением, которое говорило, что он имеет право предполагать это. Действительно, последнее письмо, полученное им из армии Мака, извещало его о победе и о самом выгодном стратегическом положении армии.
– Дай ка сюда это письмо, – сказал Кутузов, обращаясь к князю Андрею. – Вот изволите видеть. – И Кутузов, с насмешливою улыбкой на концах губ, прочел по немецки австрийскому генералу следующее место из письма эрцгерцога Фердинанда: «Wir haben vollkommen zusammengehaltene Krafte, nahe an 70 000 Mann, um den Feind, wenn er den Lech passirte, angreifen und schlagen zu konnen. Wir konnen, da wir Meister von Ulm sind, den Vortheil, auch von beiden Uferien der Donau Meister zu bleiben, nicht verlieren; mithin auch jeden Augenblick, wenn der Feind den Lech nicht passirte, die Donau ubersetzen, uns auf seine Communikations Linie werfen, die Donau unterhalb repassiren und dem Feinde, wenn er sich gegen unsere treue Allirte mit ganzer Macht wenden wollte, seine Absicht alabald vereitelien. Wir werden auf solche Weise den Zeitpunkt, wo die Kaiserlich Ruseische Armee ausgerustet sein wird, muthig entgegenharren, und sodann leicht gemeinschaftlich die Moglichkeit finden, dem Feinde das Schicksal zuzubereiten, so er verdient». [Мы имеем вполне сосредоточенные силы, около 70 000 человек, так что мы можем атаковать и разбить неприятеля в случае переправы его через Лех. Так как мы уже владеем Ульмом, то мы можем удерживать за собою выгоду командования обоими берегами Дуная, стало быть, ежеминутно, в случае если неприятель не перейдет через Лех, переправиться через Дунай, броситься на его коммуникационную линию, ниже перейти обратно Дунай и неприятелю, если он вздумает обратить всю свою силу на наших верных союзников, не дать исполнить его намерение. Таким образом мы будем бодро ожидать времени, когда императорская российская армия совсем изготовится, и затем вместе легко найдем возможность уготовить неприятелю участь, коей он заслуживает».]
Кутузов тяжело вздохнул, окончив этот период, и внимательно и ласково посмотрел на члена гофкригсрата.
– Но вы знаете, ваше превосходительство, мудрое правило, предписывающее предполагать худшее, – сказал австрийский генерал, видимо желая покончить с шутками и приступить к делу.
Он невольно оглянулся на адъютанта.
– Извините, генерал, – перебил его Кутузов и тоже поворотился к князю Андрею. – Вот что, мой любезный, возьми ты все донесения от наших лазутчиков у Козловского. Вот два письма от графа Ностица, вот письмо от его высочества эрцгерцога Фердинанда, вот еще, – сказал он, подавая ему несколько бумаг. – И из всего этого чистенько, на французском языке, составь mеmorandum, записочку, для видимости всех тех известий, которые мы о действиях австрийской армии имели. Ну, так то, и представь его превосходительству.