Oz (langage) — Wikipédia
Oz | |
Date de première version | 1995 |
---|---|
Paradigmes | objet, impératif, concurrent, fonctionnel, logique, par contraintes, distribué |
Auteurs | Gert Smolka, Christian Schulte, Hugo Sky, Peter Van Roy |
Développeurs | auteurs et d'autres contributeurs |
Dernière version | 2.0.1[1] () |
Typage | Fort, dynamique |
Influencé par | Prolog, CC, AKL, Lisp, Haskell, Erlang |
A influencé | une extension pour la programmation logique et par contraintes, dans PyPy |
Implémentations | Mozart |
Écrit en | C++ |
Système d'exploitation | Multiplate-forme |
Licences | de type BSD |
Site web | [1] |
modifier |
Oz est un langage de programmation permettant d'employer et de combiner différents paradigmes de programmation :
- fonctionnel,
- procédural et objets,
- relationnel et logique,
- contraintes,
- concurrence massive,
- distribution.
Oz fournit par défaut des variables logiques même s'il est possible d'utiliser des variables mutables. De même, l'évaluation est stricte par défaut, mais l'évaluation paresseuse est possible.
L'originalité de ce langage par rapport à d'autres supportant la programmation logique (d'une part) ou concurrente et distribuée (d'autre part, comme Erlang), est l'intégration de ces paradigmes dans un tout cohérent. Une abstraction unique en son genre est fournie par Oz : l'espace de calcul, qui permet d'encapsuler des calculs à des fins spéculatives et permet de combiner les aspects logiques/contraintes, orientation objet et mutabilité, concurrence et distribution, dans le même langage.
Oz est doté d'un ramasse-miettes et d'un système de gestion d'exceptions distribués.
Oz est implémenté par le système Mozart, fournissant un compilateur, une machine virtuelle et un environnement de développement utilisant EMACS pour la partie édition, un débogueur graphique supportant la concurrence et la distribution, un outil d'exploration d'arbres de recherche pour la programmation par contraintes, etc.
Le livre Concepts, Techniques, and Models of Computer Programming (MIT Press, 2004) utilise Oz comme langage principal pour illustrer les différents concepts de programmation. Il existe des cours universitaires de programmation en français basés sur Oz et ce livre.
Ce langage a été développé par trois écoles :
- Université catholique de Louvain (UCL - Belgique)
- université de la Sarre (Allemagne)
- Swedish Institute of Computer Science (en) (Suède).
Remarque : l'origine du nom Oz vient du fameux conte pour enfants, Le Magicien d'Oz.
Fonctionnalités du langage
[modifier | modifier le code]Structures de données
[modifier | modifier le code]Oz est basé sur un sous-ensemble du langage, appelé « langage noyau » disposant de peu de types de données qui peuvent être étendus à d'autres, plus pratiques par le biais d'un sucre syntaxique.
Structures de données de base :
- Nombres : à virgule flottante ou entier
- Enregistrement: structure de données composée permettant de regrouper de l'information :
circle(x:0 y:1 radius:3 color:blue style:dots)
. Ici, les termes x, y, radius... sont les champs (appelés « features »), avec leurs valeurs associées. « circle » est défini comme le nom du record, son « étiquette ». - Tuple: Enregistrement avec des noms de champs entiers croissants:
circle(1:0 2:1 3:3 4:blue 5:dots)
- Liste: simple structure linéaire
'|'(2 '|'(4 '|'(6 '|'(8 nil)))) % Comme un enregistrement 2|(4|(6|(8|nil))) % Avec un peu de sucre syntaxique 2|4|6|8|nil % Avec plus de sucre syntaxique [2 4 6 8] % Et avec encore plus
Ces structures de données sont des valeurs (constantes) typées dynamiquement. Les noms de variables en Oz sont écrites avec une première lettre majuscule afin de les différencier des constantes littérales[3] (atomes qui eux, commencent par une minuscule).
Fonctions
[modifier | modifier le code]Les fonctions[4] sont des valeurs de première classe, permettant la programmation d'ordre supérieur:
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}) % Pas de dépassement d'entier en Oz (tant qu'il reste de la mémoire) end fun {SumList List} case List of nil then 0 [] H|T then H+{SumList T} % Détection de forme sur liste end end
Les fonctions peuvent utiliser à la fois des variables libres et liées. Les variables libres sont trouvées par portée lexicale[5].
Programmation d'ordre supérieur
[modifier | modifier le code]Les fonctions sont comme d'autres éléments de Oz. Une fonction peut être passée comme attribut à une autre fonction ou encore être retournée par celle-ci.
fun {Square N} % Une simple fonction N*N end fun {Map F Xs} % F est une fonction ici (utilisation de la programmation d'ordre supérieur) case Xs of nil then nil [] X|Xr then {F X}|{Map F Xr} end end %Utilisation {Browse {Map Square [1 2 3]}} %Affiche [1 4 9]
Fonctions anonymes
[modifier | modifier le code]Comme de nombreux autres langages fonctionnels, Oz supporte l'utilisation de fonctions anonymes (qui n'ont pas de noms) avec la programmation d'ordre supérieur. Le symbole $ est utilisé à cet usage.
% La fonction élevée au carré est passée comme argument anonymement {Browse {Map fun {$ N} N*N end [1 2 3]}} % Affiche [1 4 9]
Comme les fonctions anonymes n'ont pas de nom, il est impossible de définir récursivement des fonctions anonymes.
Procédures
[modifier | modifier le code]Les fonctions en Oz doivent retourner une valeur comme dernière instruction de la fonction durant l'exécution. Dans l'exemple suivant, la fonction Ret retourne 5 si X > 0 et -5 dans les autres cas.
declare fun {Ret X} if X > 0 then 5 else ~5 end end
Mais Oz fournit aussi une fonctionnalité dans le cas où nous ne souhaitons pas retourner de valeur. De telles fonctions sont appelées procédures[6]. Les procédures sont définies en utilisant le mot-clef proc, comme suit:
declare proc {Ret X} if X > 0 then {Browse 5} else {Browse ~5} end end
L'exemple ci-dessus ne retourne aucune valeur, il affiche juste 5 ou -5 dans l'interface de Oz en fonction du signe de X.
Variable dataflow et concurrence déclarative
[modifier | modifier le code]Quand le programme rencontre une variable non liée, il attend une valeur:
thread Z = X+Y % Va attendre jusqu'à ce que X et Y soient liés à une valeur {Browse Z} % Affiche la valeur de Z end thread X = 40 end thread Y = 2 end
Il n'est pas possible de changer la valeur d'une variable dataflow une fois assignée (assignement unique)
X = 1 X = 2 % Erreur
Les variables dataflow rendent facile la création d'agents concurrents:
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 % Creation d'un agent qui génère un flux thread Y = {Sum 0 X} end % Création d'un agent qui traîte le flux {Browse Y} end
De par le mode de fonctionnement des variables dataflow, il est possible de placer des threads n'importe où dans le programme et il sera garanti qu'il gardera le même résultat. Ceci rend la programmation concurrente vraiment facile. Les threads sont assez légers: il est possible de faire tourner des milliers de threads à la fois [7]
Exemple : Divisions successives
[modifier | modifier le code]Cet exemple calcule un flux de nombres premiers en utilisant l'algorithme de divisions successives en créant des agents qui filtrent les nombres non premiers.
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
Paresse
[modifier | modifier le code]Oz utilise l'évaluation stricte mais aussi l'évaluation paresseuse[8] si possible:
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 % On a besoin de la valeur de X et Fact est calculée end
L'évaluation paresseuse donne la possibilité de stocker presque une infinité de structures de données en Oz. Le pouvoir de l'évaluation paresseuse peut se voir par le biais du fragment de code suivant:
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}}
Le code ci-dessus calcule de manière élégante tous les nombres premiers réguliers[9] dans une liste infinie. Les nombres réels ne sont calculés que si on les utilise.
Concurrence par envoi de messages
[modifier | modifier le code]Le modèle déclaratif concurrent peut être étendu par l'envoi de message à l'aide d'une sémantique simple:
declare local Stream Port in Port = {NewPort Stream} {Send Port 1} % Stream is now 1|_ ('_' indique une variable non liée) {Send Port 2} % Stream is now 1|2|_ ... {Send Port n} % Stream is now 1|2| .. |n|_ end
Par un port et un thread, le programmeur peut définir des agents asynchrones:
fun {NewAgent Init Fun} Msg Out in thread {FoldL Msg Fun Init Out} end {NewPort Msg} end
État et objets
[modifier | modifier le code]Il est encore possible d'étendre le model déclaratif afin de supporter l'état et la programmation orientée objet par une sémantique très simple; nous créons une nouvelle strucure mutable, les cellules (Cells).
local A X in A = {NewCell 0} A := 1 % Changes la valeur de A à 1 X = @A % @ Est utilisé pour accéder à la valeur de A end
Avec cette sémantique très simple, Oz peut supporter tout le paradigme orienté-objet. Un peu de sucre syntaxique permet d'intégrer très facilement l'OOP comme suit:
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
Notes et références
[modifier | modifier le code]- (en) « Releases · mozart/mozart2 », sur GitHub (consulté le ).
- « Mozart2 version 2.0.1 Latest », (consulté le )
- « 3 Basics », sur mozart.github.io (consulté le ).
- Leif Grönqvist, « Higher Order Functions », dans Advanced Functional Programming in Oz (lire en ligne)
- Robert Gentleman et Ross Ihaka, « Lexical Scope in Statistical Computing », dans Journal of Computational and Graphical Statistics, vol. 9, (lire en ligne), chap. 3, Systems and Languages, p. 491–508
- « 5 Basic Control Structures », sur mozart.github.io (consulté le ).
- http://www.mozart-oz.org/documentation/tutorial/node8.html#chapter.concurrency
- Paul Hudak, « Conception, evolution, and application of functional programming languages », dans ACM Computing Surveys (CSUR), vol. 21, p. 359–411
- Rao, AC and Varada Raju, D, « Application of the Hamming number technique to detect isomorphism among kinematic chains and inversions », dans Mechanism and Machine theory, vol. 26, , p. 55–75
Liens externes
[modifier | modifier le code]- (en) Mozart Programming System (mozart2.org)