Magik (langage)
Magik est un langage de Programmation orientée objet qui supporte l'héritage multiple, le polymorphisme et le typage dynamique. il a été défini et implémenté en 1989 par Arthur Chance, de Smallworld Systems Ltd, dans le cadre du système d'information géographique Smallworld. À la suite de l'acquisition par General Electric de Smallworld en 2000, Magik est maintenant distribué par GE Energy, toujours en tant que composant de la plateforme Smallworld.
Magik a été implémenté pour la première fois en 1990 et a été amélioré au fil des années. La version actuelle est la version 4.0, dite Magik SF (Small Footprint).
En , les développeurs de Magik ont annoncé le portage du langage Magik sur la machine virtuelle Java. Le succès du portage a été annoncé par Oracle Corporation en novembre de la même année[1].
Similitudes avec Smalltalk ou Python.
Magik partage avec Smalltalk, et surtout avec Python plusieurs similitudes en termes de fonctionnalités et d'architecture :
- le langage Magik est compilé à la volée en byte code, qui est exécuté par la machine virtuelle.
- il utilise un typage dynamique
- il permet l'héritage multiple
- il fonctionne particulièrement bien dans une console interactive,
- etc.
La machine virtuelle Magik est disponible sur différentes plateformes, dont Microsoft Windows, et différentes variantes d'Unix ou de Linux.
Magik est basé sur une console, et le code peut être modifié à la volée, même lorsqu'une application est en cours d'exécution. La console peut être utilisée à la fois pour exécuter du Magik ou pour voir les résultats. Le code compilé d'une application peut être enregistré dans un fichier unique, appelé fichier image, ou simplement image. Une image Magik comprend la définition des classes et variables globales, et l'état de la session. Il s'agit en fait de l'état complet de la mémoire de la machine virtuelle au moment de l'enregistrement du fichier image.
Fonctionnalités du langage
Commentaires
Magik utilise un #
pour marquer le début d'une ligne de commentaire. Chaque ligne de commentaires doit débuter par #
:
# Ceci est un commentaire.
# Ceci est un commentaire réparti # sur deux lignes
Affectation
Magik utilise l'opérateur <<
(«devient») pour les affectations :
a << 1.234
b << b + a
c << "foo" + "bar" # Concat strings
Cette notation se lit "a devient 1.234" ou "b devient b plus a". Cette terminologie permet de séparer l'affectation de la comparaison.
Magik implémente également un opérateur compressé similaire à ceux existant en C:
b +<< a # Équivalent à b << b + a
Pour imprimer la valeur d'une variable, on peut utiliser la commande suivante :
a << "hello"
write(a)
Symboles
Outre les types de données habituels, comme les entiers (integer), les réels (float) ou les chaînes de caractères, Magik implémente également des symboles. Les symboles sont utilisés abondamment en Magik pour identifier les objets de manière unique. Ils se présentent sous la forme d'un caractère :
suivi d'une chaine de caractères. Les symboles sont en principe constitués des caractères a-z (minuscules) et _, ! ou ?. Il est possible d'utiliser d'autres caractères en les plaçant entre barres verticales ( |
). Par exemple :
a << :hello # partout où :hello sera rencontré, il s'agira de la même instance
b << :|hello world|
Typage dynamique
Les variables Magik ne sont pas typées comme elles peuvent l'être en C, C++ ou Java. Elles peuvent, comme en lisp ou Python, référencer différents objets, de différentes classes, à différents moments. Magik ne différencie pas les classes et les types primitifs. En Magik, toute entité manipulée est un objet :
a << 1.2 # Un réel est affecté à la variable 'a'
a << "toto" # Puis une chaîne de caractères est affecté à la variable 'a'
- Objets
Les objets sont définis au moyen de prototypes appelés «exemplars». Ces prototypes définissent des classes, d'une manière proche de la définition des classes Python. Magik supporte l'héritage multiple, et les classes abstraites (mixins). Les nouvelles instances sont définies en clonant un objet de la classe, soit généralement le prototype, qui est lui-même une instance de la classe qu'il définit, mais tout objet de la classe peut être utilisé à la même fin.
le prototype est défini au moyen de la procédure def_slotted_exemplar()
, par exemple:
def_slotted_exemplar(:mon_objet,
{
{:slot_a, 42},
{:slot_b, "bonjour"}
}, {:classe_parente_a, :classe_parente_b})
Ce fragment de code définit une classe mon_object
qui a deux attributs («slots») appelés slot_a
(pré-initialisé à 42) et slot_b
(pré-initialisé "bonjour") qui hérite des classes classe_parente_a
et classe_parente_b
.
Comparaison
Magik implémente tous les opérateurs logiques (=
, <
, <=
, >
, >=
, ~=/<>
) pour la comparaison, ainsi que de moins habituels. Les opérateurs _is
et _isnt
sont utilisés pour comparer l'identité d'instances d'objets, plutôt que leurs valeurs.
Par exemple:
a << "Robert"
b << "Robert"
a _is b # est faux parce que les deux chaînes sont des instances différentes de la classe «chaîne de caractères».
a = b # est vrai parce que les deux valeurs sont identiques
a << "hello"
b << a
a _is b # est vrai, puisque les deux variables désignent la même instance (a a été affecté à b).
a = b # est vrai, parce que la valeur d'une même instance est forcément identique
# (il est impossible d'avoir à la fois a _is b vrai et a=b faux).
Méthodes
Les méthodes sont définies sur les exemplars au moyen des mots-clés _method
et _endmethod
:
_method mon_objet.ma_methode(a, b)
_return a + b
_endmethod
Par convention, on définit deux méthodes, new()
(pour créer une instance) et init()
(pour initialiser cette instance).
# Méthode d'instanciation
_method person.new(name, age)
_return _clone.init(name, age)
_endmethod
# méthode d'initialisation.
_private _method person.init(name, age)
# utiliser si besoin l'implémentation de la ou des classes parentes.
_super(classe_parente_a).init(name, age)
# Initialiser les slots.
.name << name
.age << age
_return _self
_endmethod
_clone
crée une copie (un clone) de l'instance de person
à laquelle le message new() a été envoyé. L'instruction _super
invoque l'implémentation de la même méthode dans la classe parente classe_parente_a
. L'instance courante est référencée au moyen du mot-clé _self
. Les valeurs des slots sont accessibles au moyen de l'opérateur unaire .
.
Les méthodes qui ne font pas partie de l'interface publique de la classe peuvent être définies au moyen du mot-clé _private
. Les méthodes «privées» ne sont accessibles qu'au moyen de _self
, _clone
, ou _super
.
Les arguments optionnels peuvent être définis au moyen du mot-clé _optional
statement. Dans ce cas, les arguments omis auront la valeur _unset
(l'objet «NUL» de Magik). Une liste variable d'arguments peut être définie au moyen de l'opérateur _gather
(«rassembler»), similaire à l'opérateur * de Python dans le cas d'arguments variables (*args).
_method my_object.my_method(_gather values)
_endmethod
Itération
En Magik les mots-clés _for
, _over
, _loop
et _endloop
permettent l'itération.
_method my_object.my_method(_gather values)
total << 0.0
_for a _over values.elements()
_loop
total +<< a
_endloop
_return total
_endmethod
m << my_object.new()
x << m.my_method(1.0, 2, 3.0, 4) # x = 10.0
Ici values.elements() est un itérateur qui permet de parcourir les valeurs. Un itérateur Magik est un type particulier de générateur, dit compréhension de liste, permettant généralement de parcourir un ensemble.
Un itérateur est défini au moyen des mots-clés _iter
et _loopbody
:
_iter _method my_object.even_elements()
_for a _over _self.elements()
_loop
_if a.even? _is _true
_then
_loopbody(a)
_endif
_endloop
_endmethod
Procédures
À l'instar de Python, Magik permet à la fois la programmation objet et/ou itérative. Magik permet donc la définition de procedures. Les procédures sont définies au moyen des mots-clés _proc
et _endproc
. Elles sont affectées à des variables pour pouvoir être invoquées :
my_procedure << _proc @my_procedure(a, b, c)
_return a + b + c
_endproc
x << my_procedure(1, 2, 3) # x = 6
Langue
Magik, ayant été développé à Cambridge, au Royaume-Uni, utilise l'anglais britannique dans ses bibliothèques . Par exemple:
Utiliser "initialise", pas "initialize" (en général, les terminaisons sont en "ise", pas ize", utiliser "centre" et non "center", etc.
Ensembles
Magik permet la manipulation d'ensembles. On peut citer :
- Simple Vector
- Rope
- Hash Table
- Property List
- Equality set
- Bags
Références
- (en) Jim Connors, « Sprinkle Some Magik on that Java Virtual Machine », (consulté le ) : « With this new capability GE Energy has succeeded in hosting their Magik environment on top of the Java Virtual Machine »
- (en) Cet article est partiellement ou en totalité issu de l’article de Wikipédia en anglais intitulé « Magik (programming language) » (voir la liste des auteurs).
Liens externes
- Smallworld Product Suite Technology
- MDT - Magik Development Tools IDE for GE Smallworld GIS developers
- Open Source (SourceForge)
- Language forum post on Magik
- Technical Paper No. 5 - An Overview of Smallworld Magik
- GE Smallworld, Emacs Extensions for Magik developers
- Thoughts on geospatial and location technology from Peter Batty