Oz (Programmiersprache) - Oz (programming language)

Oz
Paradigma Multi-Paradigma : Logik , funktional , imperativ , objektorientiert , Einschränkung , verteilt , gleichzeitig
Entworfen von Gert Smolka, seine Schüler
Entwickler Mozart-Konsortium
Erstmals erschienen 1991 ; vor 30 Jahren  ( 1991 )
Stabile Version
Oz 1.4.0 (endgültig), Mozart 2.0.1 / 5. September 2018 ; vor 2 Jahren  ( 2018-09-05 )
Schreibdisziplin dynamisch
Lizenz MIT X11
Webseite Mozart .github .io
Wichtige Implementierungen
Mozart-Programmiersystem
Dialekte
Oz, Mozart
Beeinflusst von
Erlang , Lisp , Prolog
Beeinflusst
Alice , Scala

Oz ist eine Multiparadigma-Programmiersprache , die im Programmiersystemlabor der Université catholique de Louvain für den Programmiersprachenunterricht entwickelt wurde. Es hat ein kanonisches Lehrbuch: Konzepte, Techniken und Modelle der Computerprogrammierung .

Oz wurde erstmals 1991 von Gert Smolka und seinen Schülern entworfen. 1996 wurde die Entwicklung von Oz in Zusammenarbeit mit der Forschungsgruppe von Seif Haridi und Peter Van Roy am schwedischen Institut für Informatik fortgesetzt . Seit 1999 wird Oz kontinuierlich von einer internationalen Gruppe, dem Mozart-Konsortium, weiterentwickelt, das ursprünglich aus der Universität des Saarlandes , dem schwedischen Institut für Informatik und der Université catholique de Louvain bestand . Im Jahr 2005 wurde die Verantwortung für das Management der Mozart-Entwicklung auf eine Kerngruppe, das Mozart-Board, übertragen, um die Mozart-Entwicklung ausdrücklich einer größeren Community zugänglich zu machen.

Das Mozart-Programmiersystem ist die primäre Implementierung von Oz. Es wird mit einer Open Source-Lizenz vom Mozart-Konsortium veröffentlicht. Mozart wurde auf Unix , FreeBSD , Linux , Windows und MacOS portiert .

Sprachmerkmale

Oz enthält die meisten Konzepte der wichtigsten Programmierparadigmen , einschließlich Logik, Funktion (sowohl verzögerte Bewertung als auch eifrige Bewertung ), imperative, objektorientierte, eingeschränkte, verteilte und gleichzeitige Programmierung. Oz hat sowohl eine einfache formale Semantik (siehe Kapitel 13 des unten erwähnten Buches) als auch eine effiziente Implementierung. Oz ist eine auf Parallelität ausgerichtete Sprache, wie der Begriff von Joe Armstrong, dem Hauptdesigner der Erlang-Sprache, eingeführt wurde . Eine auf Parallelität ausgerichtete Sprache macht die Parallelität einfach zu verwenden und effizient. Oz unterstützt eine kanonische grafische Benutzeroberfläche (GUI) QTk.

Neben der Multi-Paradigma-Programmierung liegen die Hauptstärken von Oz in der Constraint-Programmierung und der verteilten Programmierung . Aufgrund seines faktorisierten Designs ist Oz in der Lage, ein netzwerktransparentes verteiltes Programmiermodell erfolgreich zu implementieren. Dieses Modell erleichtert das Programmieren offener, fehlertoleranter Anwendungen innerhalb der Sprache. Für die Constraint-Programmierung führt Oz die Idee von Berechnungsräumen ein , die benutzerdefinierte Such- und Verteilungsstrategien ermöglichen, die orthogonal zur Constraint-Domäne sind.

Sprachübersicht

Datenstrukturen

Oz basiert auf einer Kernsprache mit sehr wenigen Datentypen, die durch syntaktischen Zucker zu praktischeren erweitert werden können .

Grundlegende Datenstrukturen:

  • Zahlen: Gleitkomma oder Ganzzahl (reelle Ganzzahl)
  • Datensätze: zum Gruppieren von Daten : circle(x:0 y:1 radius:3 color:blue style:dots) . Hier werden die Begriffe x, y, Radius usw. als Merkmale bezeichnet, und die den Merkmalen zugeordneten Daten (in diesem Fall 0,1,3 usw.) sind die Werte.
  • Tupel: Datensätze mit ganzzahligen Merkmalen in aufsteigender Reihenfolge : circle(1:0 2:1 3:3 4:blue 5:dots) .
  • Listen: eine einfache lineare Struktur
'|'(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

Diese Datenstrukturen sind Werte (konstant), erstklassig und dynamisch typgeprüft . Variablennamen in Oz beginnen mit einem Großbuchstaben, um sie von Literalen zu unterscheiden, die immer mit einem Kleinbuchstaben beginnen.

Funktionen

Funktionen sind erstklassige Werte, die eine funktionale Programmierung höherer Ordnung ermöglichen :

fun {Fact N}
   if N =< 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

Funktionen können sowohl mit freien als auch mit gebundenen Variablen verwendet werden. Freie Variablenwerte werden mithilfe des statischen lexikalischen Bereichs ermittelt .

Programmierung höherer Ordnung

Funktionen sind wie andere Oz-Objekte. Eine Funktion kann als Attribut an andere Funktionen übergeben oder in einer Funktion zurückgegeben werden.

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]

Anonyme Funktionen

Wie viele andere funktionale Sprachen unterstützt Oz die Verwendung anonymer Funktionen (dh Funktionen, die keinen Namen haben) mit Programmierung höherer Ordnung. Das Symbol $ bezeichnet diese.

Im Folgenden wird die Quadratfunktion anonym definiert und übergeben, wodurch [1 4 9] sie durchsucht wird.

{Browse {Map fun {$ N} N*N end [1 2 3]}}

Da anonyme Funktionen keine Namen haben, ist es nicht möglich, rekursive anonyme Funktionen zu definieren.

Verfahren

Funktionen in Oz sollen einen Wert bei der letzten Anweisung zurückgeben, die während der Ausführung im Hauptteil der Funktion angetroffen wurde. Im folgenden Beispiel gibt die Funktion Ret 5 zurück, wenn X> 0 und andernfalls -5.

declare
fun {Ret X}
   if X > 0 then 5 else ~5 end
end

Oz bietet aber auch eine Möglichkeit für den Fall, dass eine Funktion keine Werte zurückgeben darf. Solche Funktionen werden Prozeduren genannt. Prozeduren werden unter Verwendung des Konstrukts "proc" wie folgt definiert

declare
proc {Ret X}
   if X > 0 then {Browse 5} else {Browse ~5} end
end

Das obige Beispiel gibt keinen Wert zurück, sondern gibt nur 5 oder -5 im Oz-Browser aus, abhängig vom Vorzeichen von X.

Datenflussvariablen und deklarative Parallelität

Wenn das Programm auf eine ungebundene Variable stößt, wartet es auf einen Wert. Im Folgenden wartet der Thread beispielsweise, bis sowohl X als auch Y an einen Wert gebunden sind, bevor der Wert von Z angezeigt wird.

thread 
   Z = X+Y
   {Browse Z}
end
thread X = 40 end
thread Y = 2 end

Der Wert einer Datenflussvariablen kann nach dem Binden nicht mehr geändert werden:

X = 1
X = 2 % error

Datenflussvariablen erleichtern das Erstellen gleichzeitiger Stream-Agenten:

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

Aufgrund der Funktionsweise von Datenflussvariablen ist es möglich, Threads an einer beliebigen Stelle in einem Programm zu platzieren und sicherzustellen, dass das gleiche Ergebnis erzielt wird. Dies macht die gleichzeitige Programmierung sehr einfach. Threads sind sehr billig: Es ist möglich, dass 100.000 Threads gleichzeitig ausgeführt werden.

Beispiel: Probenteilungssieb

In diesem Beispiel wird ein Strom von Primzahlen mithilfe des Trial-Division- Algorithmus berechnet, indem rekursiv gleichzeitige Stream-Agenten erstellt werden, die Nicht-Primzahlen herausfiltern:

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

Faulheit

Oz verwendet standardmäßig eine eifrige Bewertung , aber eine verzögerte Bewertung ist möglich. Im Folgenden wird die Tatsache nur berechnet, wenn der Wert von X benötigt wird, um den Wert von Y zu berechnen.

fun lazy {Fact N}
   if N =< 0 then 1 else N*{Fact N-1} end
end
local X Y in
  X = {Fact 100} 
  Y = X + 1
end

Eine verzögerte Auswertung bietet die Möglichkeit, wirklich unendliche Datenstrukturen in Oz zu speichern. Die Leistungsfähigkeit der verzögerten Auswertung ist aus dem folgenden Codebeispiel ersichtlich:

declare
fun lazy {Merge Xs Ys}
   case Xs#Ys
   of (X|Xr)#(Y|Yr) then
      if X < Y then X|{Merge Xr Ys}
      elseif X>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}}

Der obige Code berechnet elegant alle regulären Zahlen in einer unendlichen Liste. Die tatsächlichen Zahlen werden nur berechnet, wenn sie benötigt werden.

Parallelität der Nachrichtenübermittlung

Das deklarative gleichzeitige Modell kann durch einfache Semantik um die Nachrichtenübermittlung erweitert werden :

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

Mit einem Port und einem Thread können asynchrone Agenten definiert werden:

fun {NewAgent Init Fun}
   Msg Out in
   thread {FoldL Msg Fun Init Out} end
   {NewPort Msg}
end

Zustand und Objekte

Es ist wieder möglich, das deklarative Modell zu erweitern, um zustands- und objektorientierte Programmierung mit sehr einfacher Semantik zu unterstützen. So erstellen Sie eine neue veränderbare Datenstruktur mit dem Namen "Zellen":

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

Mit diesen einfachen semantischen Änderungen kann das gesamte objektorientierte Paradigma unterstützt werden. Mit ein wenig syntaktischem Zucker wird OOP gut in Oz integriert.

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

Ausführungsgeschwindigkeit

Die Ausführungsgeschwindigkeit eines vom Mozart-Compiler (Version 1.4.0, das Oz 3 implementiert) erstellten Programms ist sehr langsam. Bei einer Reihe von Benchmarks ist der Durchschnitt etwa 50-mal langsamer als bei der GNU Compiler Collection (GCC) für die Sprache C, wodurch die Benchmark-Aufgaben gelöst werden.

Siehe auch

Verweise

Externe Links