Парадигма | мультипарадигма : логическая, функциональная, императивная, объектно-ориентированная, ограниченная, распределенная, параллельная |
---|---|
Разработано | Герт Смолка, его ученики |
Разработчик | Консорциум Моцарта |
Впервые появился | 1991 ; 30 лет назад ( 1991 ) |
Стабильный выпуск | Оз 1.4.0 (финал), Моцарт 2.0.1 / 5 сентября 2018 года ; 2 года назад ( 2018-09-05 ) |
Печатная дисциплина | динамичный |
Лицензия | MIT X11 |
Веб-сайт | Моцарт.github.io |
Основные реализации | |
Система программирования Моцарта | |
Диалекты | |
Оз, Моцарт | |
Под влиянием | |
Эрланг, Лисп, Пролог | |
Под влиянием | |
Алиса, Скала |
Oz - это многопарадигмальный язык программирования, разработанный в Лаборатории систем программирования при Католическом университете Лувена для обучения языку программирования. У него есть канонический учебник: « Концепции, методы и модели компьютерного программирования».
Oz был впервые разработан Гертом Смолкой и его учениками в 1991 году. В 1996 году разработка Oz продолжилась в сотрудничестве с исследовательской группой Сейфа Хариди и Питера Ван Роя из Шведского института компьютерных наук. С 1999 года Oz постоянно разрабатывается международной группой Mozart Consortium, которая первоначально состояла из Саарландского университета, Шведского института компьютерных наук и Католического университета Лувена. В 2005 году ответственность за управление разработкой Моцарта была передана основной группе, Совету Моцарта, с явной целью открыть развитие Моцарта для более широкого сообщества.
Система программирования Моцарта - это основная реализация Oz. Он выпущен Консорциумом Моцарта с открытым исходным кодом. Моцарт был портирован на Unix, FreeBSD, Linux, Windows и macOS.
Oz содержит большинство концепций основных парадигм программирования, включая логическое, функциональное (как ленивое вычисление, так и активное вычисление ), императивное, объектно-ориентированное, ограниченное, распределенное и параллельное программирование. Oz имеет как простую формальную семантику (см. Главу 13 упомянутой ниже книги), так и эффективную реализацию. Oz - это язык, ориентированный на параллелизм, поскольку этот термин был введен Джо Армстронгом, главным разработчиком языка Erlang. Язык, ориентированный на параллелизм, делает параллелизм простым и эффективным. Oz поддерживает канонический язык графического интерфейса пользователя (GUI) QTk.
Помимо многопарадигмального программирования, основные сильные стороны Oz заключаются в программировании с ограничениями и распределенном программировании. Благодаря продуманному дизайну Oz может успешно реализовать прозрачную для сети модель распределенного программирования. Эта модель упрощает программирование открытых отказоустойчивых приложений на языке. Для программирования с ограничениями Оз вводит идею вычислительных пространств, которые позволяют определять пользовательские стратегии поиска и распределения, ортогональные области ограничений.
Oz основан на базовом языке с очень небольшим количеством типов данных, которые можно расширить до более практичных с помощью синтаксического сахара.
Базовые структуры данных:
circle(x:0 y:1 radius:3 color:blue style:dots)
. Здесь термины x, y, радиус и т. Д. Называются элементами, а данные, связанные с элементами (в данном случае 0,1,3 и т. Д.), Являются значениями. circle(1:0 2:1 3:3 4:blue 5:dots)
.'|'(2 '|'(4 '|'(6 '|'(8 nil)))) % as a record. 2|(4|(6|(8|nil))) % with some syntactic sugar 2|4|6|8|nil % more syntactic sugar [2 4 6 8] % even more syntactic sugar
Эти структуры данных являются значениями (константами), проверяются первым классом и динамически типом. Имена переменных в Oz начинаются с заглавной буквы, чтобы отличать их от литералов, которые всегда начинаются со строчной буквы.
Функции - это значения первого класса, позволяющие функциональное программирование более высокого порядка :
fun {Fact N} if N =lt; 0 then 1 else N*{Fact N-1} end end
fun {Comb N K} {Fact N} div ({Fact K} * {Fact N-K}) % integers can't overflow in Oz (unless no memory is left) end fun {SumList List} case List of nil then 0 [] H|T then H+{SumList T} % pattern matching on lists end end
Функции могут использоваться как со свободными, так и со связанными переменными. Свободные значения переменных находятся с использованием статической лексической области видимости.
Функции похожи на другие объекты Oz. Функция может быть передана как атрибут другим функциям или может быть возвращена функцией.
fun {Square N} % A general function N*N end fun {Map F Xs} % F is a function here - higher order programming case Xs of nil then nil [] X|Xr then {F X}|{Map F Xr} end end %usage {Browse {Map Square [1 2 3]}} %browses [1 4 9]
Как и многие другие функциональные языки, Oz поддерживает использование анонимных функций (т.е. функций, не имеющих имени) с программированием более высокого порядка. Для их обозначения используется символ $.
Далее функция square определяется анонимно и передается, вызывая [1 4 9]
просмотр.
{Browse {Map fun {$ N} N*N end [1 2 3]}}
Поскольку анонимные функции не имеют имен, невозможно определить рекурсивные анонимные функции.
Функции в Oz должны возвращать значение в последнем операторе, встречающемся в теле функции во время ее выполнения. В приведенном ниже примере функция Ret возвращает 5, если Xgt; 0, и -5 в противном случае.
declare fun {Ret X} if X gt; 0 then 5 else ~5 end end
Но Oz также предоставляет возможность на случай, если функция не должна возвращать значения. Такие функции называются процедурами. Процедуры определяются с помощью конструкции "proc" следующим образом.
declare proc {Ret X} if X gt; 0 then {Browse 5} else {Browse ~5} end end
Приведенный выше пример не возвращает никакого значения, он просто печатает 5 или -5 в браузере Oz в зависимости от знака X.
Когда программа встречает несвязанную переменную, она ждет значения. Например, ниже поток будет ждать, пока X и Y не будут привязаны к значению, прежде чем отобразить значение Z.
thread Z = X+Y {Browse Z} end thread X = 40 end thread Y = 2 end
Значение переменной потока данных не может быть изменено после привязки:
X = 1 X = 2 % error
Переменные потока данных упрощают создание параллельных потоковых агентов:
fun {Ints N Max} if N == Max then nil else {Delay 1000} N|{Ints N+1 Max} end end fun {Sum S Stream} case Stream of nil then S [] H|T then S|{Sum H+S T} end end local X Y in thread X = {Ints 0 1000} end thread Y = {Sum 0 X} end {Browse Y} end
Из-за того, как работают переменные потока данных, можно разместить потоки в любом месте программы и гарантировать тот же результат. Это очень упрощает параллельное программирование. Потоки очень дешевы: за один раз можно запустить 100 000 потоков.
В этом примере вычисляется поток простых чисел с использованием алгоритма пробного деления путем рекурсивного создания параллельных потоковых агентов, которые отфильтровывают непростые числа:
fun {Sieve Xs} case Xs of nil then nil [] X|Xr then Ys in thread Ys = {Filter Xr fun {$ Y} Y mod X \= 0 end} end X|{Sieve Ys} end end
Оз по умолчанию использует нетерпеливую оценку, но ленивая оценка возможна. Ниже этот факт вычисляется только тогда, когда значение X необходимо для вычисления значения Y.
fun lazy {Fact N} if N =lt; 0 then 1 else N*{Fact N-1} end end local X Y in X = {Fact 100} Y = X + 1 end
Ленивое вычисление дает возможность хранить действительно бесконечные структуры данных в Oz. Мощь ленивого вычисления можно увидеть в следующем примере кода:
declare fun lazy {Merge Xs Ys} case Xs#Ys of (X|Xr)#(Y|Yr) then if X lt; Y then X|{Merge Xr Ys} elseif Xgt;Y then Y|{Merge Xs Yr} else X|{Merge Xr Yr} end end end fun lazy {Times N Xs} case Xs of nil then nil [] X|Xr then N*X|{Times N Xr} end end declare H H = 1 | {Merge {Times 2 H} {Merge {Times 3 H} {Times 5 H}}} {Browse {List.take H 6}}
Приведенный выше код элегантно вычисляет все регулярные числа в бесконечном списке. Фактические числа вычисляются только тогда, когда они необходимы.
Декларативная конкурентная модель может быть расширена за счет передачи сообщений с помощью простой семантики:
declare local Stream Port in Port = {NewPort Stream} {Send Port 1} % Stream is now 1|_ ('_' indicates an unbound and unnamed variable) {Send Port 2} % Stream is now 1|2|_... {Send Port n} % Stream is now 1|2|.. |n|_ end
С помощью порта и потока можно определить асинхронные агенты:
fun {NewAgent Init Fun} Msg Out in thread {FoldL Msg Fun Init Out} end {NewPort Msg} end
Снова появилась возможность расширить декларативную модель для поддержки государственного и объектно-ориентированного программирования с очень простой семантикой. Чтобы создать новую изменяемую структуру данных под названием Cells:
local A X in A = {NewCell 0} A:= 1 % changes the value of A to 1 X = @A % @ is used to access the value of A end
С помощью этих простых семантических изменений может поддерживаться вся объектно-ориентированная парадигма. С небольшим синтаксическим сахаром ООП становится хорошо интегрированным в Оз.
class Counter attr val meth init(Value) val:=Value end meth browse {Browse @val} end meth inc(Value) val:=@val+Value end end local C in C = {New Counter init(0)} {C inc(6)} {C browse} end
Скорость выполнения программы, созданной компилятором Моцарта (версия 1.4.0, реализующая Oz 3), очень низкая. По набору тестов он в среднем примерно в 50 раз медленнее, чем у GNU Compiler Collection (GCC) для языка C, решая тестовые задачи.