OCaml (Objective Caml)

Материал из Национальной библиотеки им. Н. Э. Баумана
Последнее изменение этой страницы: 20:01, 1 июня 2016.
Objective Caml
Caml.128x58.gif
Парадигма мультипарадигменный: функциональный, объектно-ориентированный, императивный
Спроектировано INRIA
Стабильная версия 4.02.1 / 14 октября 2014
Печать дисциплины строгая, статическая
Лицензия публичная лицензия Q
Портал: http://ocaml.org
Диалект
F#, JoCaml, MetaOCaml, OcamlP3l
Под влиянием
Standard ML, Caml Light

OCaml (Objective Caml) - объектно-ориентированный язык функционального программирования, который был разработан с учётом безопасности исполнения и надёжности программ. Язык поддерживает функциональную, императивную и объектно-ориентированную парадигмы программирования.Самый распространённый в практической работе диалект языка ML.Инструментарий OCaml включает в себя интерпретатор, компилятор в байткод и оптимизирующий компилятор в машинный код, сравнимый по эффективности с Java и лишь немного уступающий по быстродействию C и C++. В языке используется сборка мусора, а большинство типов данных поставлено в рамки, что означает предотвращение переполнения буферов во время исполнения программы. Кроме того, статическая типизация и проверки времени компиляции делают невозможными некоторые другие классы ошибок, такие как ошибки приведения типов, в силу отсутствия автоматического приведения типов. Кроме того, код может быть формально верифицирован. Имеются утилиты автоматического доказательства типовой корректности кода, превосходящие таковые для большинства языков программирования. OCaml, как и другие диалекты ML, используются в исследовательских задачах и задачах верификации, при котором основной код пишется на некотором языке программирования, а затем формально верифицируется и анализируется программой на OCaml. Например, на OCaml написана система интерактивного доказательства теорем Coq.

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

Среди особенностей языка можно выделить:

  1. Статическая проверка типов
  2. Параметрический полиморфизм
  3. Алгебраические типы данных и сопоставление с образцом
  4. Поддержка программирования с неизменяемыми структурами данных
  5. Автоматическая сборка мусора
  6. Эффективный компилятор в машинный код, без применения JIT-компиляции

Семантика

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

 let count = 0;;
 let size = 5;;

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

 let area radius = let pi = 3.14 in radius *. radius *. pi ;;

Функции

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

 function x -> x + 1

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

 (function x -> x + 1) 5

Типом этой функции является int -> int. Функция может иметь несколько аргументов:

 function (x, y) -> x - y

В этом примере её тип: int * int -> int, то есть, на входе функции - пара, а на выходе - целое. Есть и другой подход представления функций нескольких аргументов — преобразование N-арной функции в N функций одного аргумента — каррирование.

 function x -> function y -> x * y

Именованные функции можно получить, связав переменную с функцией. Определение именованной функции настолько частая операция, что имеет отдельную синтаксическую поддержку:

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

Типы

Язык OCaml имеет несколько примитивных типов: числовые типы, символьный, строки символов, логический.

  1. Целый тип представляет целые числа из интервала [-230, 230 - 1] и [-262, 262 - 1] для 32- и 64-битных архитектур соответственно. В случае выхода результата за допустимый интервал ошибки не происходит, а результат вычисляется по модулю границы интервала.
  2. Числа с плавающей запятой представляются 53-битной мантиссой и порядком из интервала [−1022, 1023]. В операциях эти числа нельзя смешивать с целыми. Кроме того, операции над числами с плавающей запятой синтаксически отличаются от целочисленных операций: +., -., *., /.. Также имеется операция возведения в степень: **. Для преобразования целых чисел в числа с плавающей запятой и обратно доступны функции: float_of_int и int_of_float.
  3. Символьный тип - char - соответствует представлению символа с кодом от 0 до 255 (первые 128 символов совпадают с ASCII). Строчный тип - string - последовательность символов.
  4. Логический тип имеет два значения: true (истина) и false (ложь). Операции над величинами логического типа: унарная not (отрицание), бинарные: && (и), || (или). Логические значения получаются в результате сравнений: = (структурное равенство), == (тождество), <> (отрицание структурного равенства), != (отрицание тождества), <, >, <=, >=. Для примитивных типов кроме строк и чисел с плавающей точкой структурное равенство и тождество совпадают, для других типов тождественными считаются значения, располагающиеся по одному адресу в памяти, а при структурном сравнении значения проверяются по-компонентно.

Объекты в языке OCaml

Классы

OCaml объектно-ориентированный язык. Класс "point", который показан ниже, определяет член класса x и два метода "get_x" и "move". Переменная x инициализируется значением "init_x". Переменная х определена как изменяющаяся, поэтому метод "move" может изменить ее значение.

 class point init_x=
    object
       val mutable x = init_x
       method get_x = x
       method move d = x <- x + d
    end;;

Создание нового объекта "point" выглядит следующим образом:

 let p = new point 5;;

Символ # используется для вызова методов.

 p#get_x
 p#move 3

Наследование

Наследование класса цветной точка (colored_point) от класса точки показано ниже. Этот класс содержит в себе все члены и все методы класса точки (point), и новый член "с" и новый метод "color".

 class colored_point x (c : string) =
    object
       inherit point x
       val c = c
       method color = c
    end;;
 let p’ = new colored_point 5 "red";;

"point" и "colored_point" несовместимые типы, потому что класс точки не имеет метода "color". Однако, функция get_x общая для всех объектов которые ее имеют.

Инициализаторы

Привязки внутри определения класса оцениваются, прежде чем объект создается. Кроме того, можно сразу вычислить выражение после того как объект был создан. Такой код пишется как анонимный метод и называется скрытым инициализатором. Таким образом он может получить доступ к членам класса и ссылке на объект.

 class printable_point x_init =
    let origin = (x_init / 10) * 10 in
    object (self)
       val mutable x = origin
       method get_x = x
       method move d = x <- x + d
       method print = print_int self#get_x
       initializer print_string "new point at "; self#print; print_newline()
    end;;

В этом примере "origin" является скрытым инициализатором.

Множественное наследование

Множественное наследование разрешено. Только последнее определение метода сохраняется. Переопределение метода в дочернем классе, который доступен в родительском классе, перекрывает определение в родительском классе. Ниже "super" связан с родителем "printable_point". "super" является псевдопеременной, которая может быть использована только для вызова метода родительского класса, как super#print.

 class printable_colored_point y c =
    object (self)
       val c = c
       method color = c
       inherit printable_point y as super
       method print =
          print_string "(";
          super#print;
          print_string ", ";
          print_string (self#color);
          print_string ")"
    end;;

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

Циклы

В языке OCaml есть циклы for и while

 for <начальное значение> to <конечное значение> do
 done;;

В отличии от других языков, в языке OCaml параметр цикла принимает на последней итерации значение равное конечному значению. Например:

 for i = 0 to 5 do 
     Printf.printf "%d" i
 done;;

В результате получится:

012345

Синтаксис цикла while приведен ниже:

 while <условие> do
 done;;

В качестве условия можно задать любое выражение которое принимает логическое значение. Например:

 let i = 0;;
 while i < 5 do
    incr(i)
 done;

Компиляция

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

ocaml

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

 print_endline "Hello World!"

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

ocamlc hello.ml -o hello

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

ocamlopt hello.ml -o hello

и запущена:

./hello

Список литературы

  1. OCaml for the Masses
  2. Официальный сайт языка OCaml
  3. Ксавье Лерой, Документация и руководство пользователя
  4. https://ru.wikipedia.org/wiki/OCaml