Logo
  Erlang-fr.org  

Présentation du site
Cours Erlang
Articles
Projets
Autour d'Erlang-fr
Liens
 
English Area
Miroir: Documentation Erlang
Miroir: Archives Erlang/OTP
 
Recherche

Logo Process-one
Erlang

Débuter avec Erlang

Article original traduit par Philippe Midol-Monnet.

1 Débuter avec Erlang

1.1 Introduction

Ce chapitre décrit les opérations les plus courantes effectées avec Erlang/OTP et est destiné aux lecteurs utilisant Erlang/OTP pour la première fois. Il contient aussi des références vers des sources d'informations plus détaillés.

Ce document considère que vous avez accès à d'autres sources d'informations sur le fonctionnement du langage Erlang. Le premier chapitre du livre Concurrent Programming in ERLANG est diponible en ligne au format PDF (En anglais).

Ce manuel décrit comment:

  • compiler et lancer des programmes Erlang,

  • travailler avec le shell Erlang, qui est l'environnement central de développement,

  • utiliser les outils de bases, le debugger et le gestionnaire de process,

Ce manuel décrit aussi les différences entre les environnements de développement sur les plateformes Unix et Windows.

1.1.1 Conventions utilisées dans ce document

Les conventions suivantes ont été utilisées pour décrire les commandes saisies au clavier dans le shell Erlang, ou dans la ligne de commande Emacs.

  • pour saisir la commande C-c: Appuyer sur la touche Control et la lettre c simultanément. C-c est équivalent à ^c.

  • pour saisir la commande M-f: Appuyer et relacher la touche Esc, puis appuyer sur la touche f.

  • pour saisir la commande halt( ). Taper halt( ). puis appuyer sur Entrée. Vous devez saisir le point qui termine la commande.

  • le prompt Unix est >.

  • le prompt dos est C:\>

1.2 Travailler avec Erlang

Les programmes Erlang sont lancés quand vous le demandez au moteur d'exécution d'Erlang (Erlang runtime system) (ERTS) d'exécuter votre code. Ce ne sont pas des programmes binaires qui peuvent être exécutés directement par votre ordinateur. ERTS est constitué d'un «évaluateur» de code (evaluator) Erlang et de plusieurs bibliothèques. L'évaluateur d'Erlang est aussi considéré comme un émulateur et ressemble beaucoup à la machine virtuelle Java.

ERTS réunis à de nombreux composants prêt à l'emploi et un ensemble de principes de conception compose l'Open Telecom Platform, appelé aussi OTP ou Erlang/OTP.

La partie centrale de l'environnement de développement d'Erlang/OTP est le shell Erlang, erl. erl est disponible sur système Unix, Windows NT/2000 et Windows 95/98. Il ressemble beaucoup à un shell Unix, au DOS sous Windows ou à la fenêtre de commande Windows NT. La différence est que le shell Erlang comprend comment:

  • compiler et charger des programmes Erlang,

  • exécuter des programmes Erlang, des fonctions individuelles ou évaluer des expressions Erlang,

  • surveiller et contrôler l'exécution des programmes,

  • éditer la ligne de commande,

  • gérer l'historique des commandes précédemment saisies,

En plus de cette interface textuelle, il existe plusieurs outils comportant une interface graphique, comme le debugger ou le gestionnaire de process.

Vous pouvez effectuer toutes les opérations depuis cette interface de commande, mais vous pouvez aussi activer la barre d'outils, ou vous trouverez des boutons permettant de lancer les outils graphiques.

1.2.1 Lancement d'Erlang/OTP

Pour démarrer Erlang/OTP sur un syteme Unix, vous lancer dans un shell, la commande suivante:

> erl -s toolbar
      

Sur une plateforme Windows, vous pouvez lancez Erlang/OTP en choisissant l'option Erlang with Toolbar dans le menu démarrer. Si l'exécutable d'Erlang/OTP est présent dans votre «chemin d'exécution» (execution path), vous pouvez aussi le lancer dans une fenêtre DOS ou par une ligne de commande NT avec:

C:\> werl -s toolbar 
      

Note!

Sur une plateforme Windows, il existe deux exécutables, erl et werl. Normallement, vous utilisez werl, voir le manuel de référence werl pour plus de détails.

Les informations suivantes apparaissent a l'écran:

Erlang (BEAM) emulator version 4.9
 
Eshell V4.9  (abort with ^G)
1> 
      

Le shell Erlang est maintenant prêt à recevoir vos instructions. Ces commandes peuvent être n'importe quelle expression compréhensible par un shell Erlang.

Essayez en tapant 1 + 2. suivi de la touche Entrée (n'oubliez pas le point final). Vous pouvez aussi appeler une des fonctions intégrées, tapez date().. Le résultat de ce que vous avez saisie ressemblera à

Erlang (BEAM) emulator version 4.9
 
Eshell V4.9  (abort with ^G)
1> 1 + 2.
3
2> date().
{1998,1,22}
        

L'exemple ci-dessus peut être vu comme un dialogue avec le moteur d'exécution. Vous pouvez aussi lancer des fonctions ou des programmes, envoyer des messages ou contrôler des process.

Pour arrêter Erlang/OTP, saisissez une des commandes suivantes dans la fenêtre d'exécution:

  1. Entrez la commande C-c (appuyez sur la touche Contrôle et la lettre c simultanément).
    Cette commande fait passer en mode BREAK, et le systeme répond:

    BREAK: (a)bort (c)ontinue (p)roc info (i)nfo (l)oaded
    (v)ersion (k)ill (D)b-tables (d)istribution
              
    Tapez a et appuyez sur la touche Entrée pour stopper Erlang.

  2. Saisissez la commande halt( ). et appuyez sur la touche Entrée.

  3. Entrez la commande C-g et appuyez sur la touche Entrée. Cette commande donne le prompt -->
    appuyez sur q pour quitter et validez par la touche Entrée pour arrêter Erlang/OTP.

1.2.2 Démarrage des outils

Vous pouvez démarrer différents outils depuis la barre d'outils.

starterl_fig4.1
La barre d'outils (Toolbar)

1.2.3 Compiler un fichier

Cette section décrit coment compiler et exécuter un programme Erlang simple en utilisant le shell Erlang. Nous considérons que le programme suivant, qui calcul la factoriel d'un entier, a été créé avec un éditeurs externe, et qu'il a été sauvé sous le nom de math1.erl.

Assurez vous que vous êtes dans le répertoire, ou se trouve le fichier contenant le programme. Vous pouvez utilisez la commande pwd(). pour le vérifier, si nécessaire, changez de répertoire en utilisant la commande cd(Dir)..

-module(math1).
-export([factorial/1]).
factorial(0) -> 1;
factorial(N) -> N * factorial(N-1).
      

Suivez les indications suivantes pour compiler le programme:

  1. Entrez la commande c(math1)..
    1> c(math1).
    {ok,math1}
    2>
          

  2. Le système répond {ok, math1} si la compilation c'est bien déroulée. Sinon, le compilateur affiche un mesage d'erreur au format suivant:
    math1.erl: line number: error message
              

Voir la section Compilation dans ce chapitre pour plus d'information sur la compilation du code

1.2.4 Evaluer une expression

Quand un module a été compilé avec succès, les fonctions exportées de ce modules peuvent être évaluées en saisissant l'expression au prompt du shell Erlang, suivi par un point et un retour chariot.

L'exemple suivant illustre une évaluation, utilisant le programme math1.erl:

  • Saisissez l'expression suivante sur la ligne de commande:
    math1:factorial(45).
              

  • Erlang évalue l'expression et affiche le résultat. Celui de l'expression saisie ressemble à:
    2> math1:factorial(45).
    119622220865480194561963161495657715064383733760000000000
    3>
              

Note!

Toutes les expressions Erlang doivent se terminer par un point.

1.2.5 Arrèter l'évaluation d'une expression

Entrez C-c. pour stopper une évaluation (appuyez sur la touche Control et la lettre c simultanément). Cette action permet aussi de terminer une boucle infinie.

1.2.6 Comment obtenir de l'aide

Le langage Erlang lui-même est décris dans le livre Concurrent Programming in ERLANG , qui est disponible en ligne au format PDF.

NdT : Concurrent se traduit par concourrant (aller ensemble) et non par concurrent (l'inverse).

La documentation complète au format HTML peut-être téléchargée avec l'environnement de développement lui-même (Archive). Elle est aussi disponible en ligne

Depuis un shell Unix vous pouvez accéder aux pages de manuel des bibliothèques d'Erlang/OTP. Par exemple pour visualiser le manuel du module intitulé lists vous tapez

% erl -man lists
      

Vous pouver lister les commandes du shell Erlang en tapant

1> help().
      

1.3 Le shell Erlang

Le shell Erlang est un programme donnant accès à l'«évaluateur» Erlang. Les commandes éditées, les commandes internes du shell, et les expressions Erlang, qui sont saisies dans la fenêtre du shell sont interprétées par l'«évaluateur» Erlang.

Dans le shell il est possible:

  • d'évaluer des expressions,

  • de rappeller les expressions précédentes,

  • d'affecter et de détruire des variables,

  • de manipuler les travaux (jobs) concourants.

En fonction de votre environnement de travail, démarrer Erlang/OTP, d'une des façons suivantes:

  • Sur un système Unix vous entrez la commande erl à l'invite du shell. Cette commande lance le «moteur d'exécution» et le shell Erlang

  • Sous Windows vous démarrez normalemment Erlang/OTP depuis le menu démarrer. Vous pouvez aussi entrer la commande erl ou werl depuis une fenêtre DOS, ou sur une ligne de commande. Notez que l'utilisation de la commande erl vous donnera accès a un shell plus primitif qu'avec la commande werl, consultez le manuel de référence de werl pour plus de détails.

starterl_fig4.2
Le menu d'Erlang/OTP sur Windows

Hormis l'évaluation des commandes et des expressions, le shell a les propriétés suivantes:

  • L'«affectation» (binding) des variables est mémorisé.

  • Les modifications du dictionnaire du process local (get et put) sont mémorisés.

  • Les nouvelles affectations et modifications du dictionnaire du process local sont perdues si une expression est saisie et que son évaluation échoue. Dans ce cas, les anciennes valeurs sont rétablies.

  • Les travaux peuvent être manipulés dans le shell. Un travail peut être vu comme un ensemble de process qui peuvent communiquer avec le shell.

Le shell peut fonctionner en deux modes différents:

  • Mode normal, dans lequel les commandes peuvent être éditées et les expressions évaluées.

  • Job control mode (JCL), dans lequel les travaux (jobs) peuvent être démarrés, stoppés, détachés ou connectés. Seul le travail courant peut communiquer avec le shell.

1.3.1 Commandes d'édition

L'utilisateur peut éditer les commandes grace à un sous-ensemble des commandes d'édition d'Emacs. Ces commandes sont listées dans le tableau suivant.

Séquence de touches Fonction
C-a Début de ligne
C-b En arrière d'un caratère
M-b En arrière d'un mot
C-d Suppression d'un caractère
M-d Suppression d'un mot
C-e Fin de ligne
C-f En avant d'un caractère
M-f En avant d'un mot
C-g Entrer en mode break du shell
C-k Suppression d'une ligne
C-l Réaffiche la ligne
C-n Rappel la ligne suivante de l'historique
C-p Rappel la ligne précédente de l'historique
C-t Echange deux caractères
M-t Echange deux mots
C-y Insertion du texte préalablement suprimé
Edition de texte

Note!

La notation C-a signifie presser simultanément la touche controle et la lettre a simultaneously. M-f signifie presser la touche ESC suivie de la lettre f.

La touche Esc est aussi appelé touche Meta dans l'environnement Unix.

La touche Tabulation peut être utilisée pour compléter le nom des fonctions et des modules.

1.3.2 Commandes Interne du Shell

Le shell possède d'origine plusieurs commandes internes. La commande help() affiche les commandes suivantes:

1> help().
** shell internal commands **
b()             -- display all variable bindings
e(N)            -- repeat the expression in query <N>
f()             -- forget all variable bindings
h()             -- history
v(N)            -- use the value of query <N>
** commands in module c **
c(File)         -- compile and load code in <File>
cd(Dir)         -- cd Dir .. example cd("..")
flush()         -- flush any messages sent to the shell
help()          -- help info
i()             -- information about the system
ni()            -- information about the networked system
i(X,Y,X)        -- information about pid <X,Y,Z>
l(File)         -- Load module in <File>
lc([File])      -- Compile a list of Erlang modules
ls()            -- list files in the current directory
ls(Dir)         -- list files in directory <Dir>
m()             -- which modules are loaded
m(Mod)          -- information about module <Mod>
nc(File)        -- compile and load code in <File> on all nodes
nl(File)        -- Load module in <File> on all nodes
pid(X,Y,Z)      -- convert X,Y,Z to a Pid
pwd()           -- print working directory
regs()          -- information about registered processes
nregs()         -- information about all registered processes
** commands in module i (interpreter interface) **
ih()            -- print help for the i module
true
2> 
      

Quand une expression au format Func(Arg1,Arg2,...,ArgN) est saisie, le shell doit déterminer a quoi se réfere Func avant que l'expression puisse être évaluée. Il interprète Func dans l'ordre suivant de priorité:

  1. Func fait référence a un objet fonctionnel (Fun)

  2. Func fait référence à une fonction de base (built in function: BIF)

  3. user_default:Func dans le module user_default

  4. shell_default:Func dans le module shell_default

1.3.3 Exemple de dialogue avec le Shell

Ce qui suit est un dialogue complet avec le shell. Des explications détaillées sont données pour chaque commandes.

host_prompt> erl
Eshell V4.4 (abort with ^G)
1> Str = "abcd".
"abcd"
      

La commande 1 positionnne la variable Str a la chaîne "abcd". Remember that "..." is the shorthand for the list of ASCII integers which represents the string.

2> L = length(Str).
4
      

La commande 2 "compare la forme" (matches the pattern) de L avec la valeur de retour de length(Str). Comme L n'est liée a aucune valeur la comparaison réussie et 4 est affecté à L.

3> Descriptor = {L, list_to_atom(Str)}.
{4,abcd}
      

La commande 3 affecte la variable Descriptor au tuple {4,abcd}.

4> L.
4
      

La commande 4 affiche la valeur de la variable L.

5> b().
Descriptor = {4,abcd}
L = 4
Str = "abcd"
ok
      

La commande 5 évalue la commande interne du shell b() (acronyme de bindings: Liaison). Ceci affiche la liste des variables courantes du shell et leurs valeurs.

6> f(L).
ok
      

La commande 6 évalue la commande interne du shell f(L) (initiale de forget: oublier) qui oublie («désapprend») la valeur de la variable L .

7> b().
Descriptor = {4,abcd}
Str = "abcd"
ok
      

La commande 7 retourne la liste des variables et de leurs contenus. La variable L n'apparaît plus.

8> {L, _} = Descriptor.
{4,abcd}
      

La commande 8 effectue une opération d'appariement en fonction d'un modèle, avec Descriptor, affectant une nouvelle valeur à L.

9> L.
4
      

La commande 9 évalue L et affichez sa valeur.

10> {P, Q, R} = Descriptor.
** exited: {{badmatch,{4,abcd},{erl_eval,expr,3}} **
      

La commande 10 tente d'apparier {P, Q, R} avec Descriptor qui contient {4, abc}. L'appariement échoue et aucune de ces nouvelles variables ne sont affectées. "** exited: badmatch ... ... **" est affiché. Ce n'est pas la valeur de l'expression, et une expression n'a aucune valeur tant que son évaluation échoue. C'est un message d'avertissement affiché par le système, pour informer qu'une erreur c'est produite. Les informations affichées après le mot badmatch indiquent quel terme était en train d'etre apparié, et dans quel fonction l'erreur c'est produite. Les valeurs des autres variables comme L et Str sont inchangées.

11> P.
** exited: {{unbound, 'P'},{erl_eval, expr, 3}} **
      
12> Descriptor.
{4,abcd}
      

Les commandes 11 et 12 montrent que P ne contient aucune valeur et n'existe pas et que Descriptor n'a pas été modifié.

13> {P, Q} = Descriptor.
{4,abcd}
      
14> P.
4
      

Les commandes 13 et 14 montrent un appariement réussi, dans lequel P et Q sont affectées.

15> f().
ok.
      

La commande 15 efface toutes les affectations

Pour les autres commandes nous utiliserons le module test1 défini de la manière suivante:

-module (test1).
-export ([demo/1]).
demo(X) ->
put(aa, worked),
X = 1,
X + 10.
      

Compilez le par c(test1). et continuez avec la commande 16

16> put(aa, hello).
undefined
17> get(aa).
hello
      

Les commandes 16 et 17 positionne et vérife la valeur de l'objet aa dans le dictionnaire du process.

18> Y = test1:demo(1).
11
19> get().
[{aa, worked}]
      

La commande 18 évalue test1:demo(1), cette évaluation réussie et les modifications effectuées dans le dictionnaire du process deviennent visible dans le shell. La nouvelle valeur de l'objet aa du dictionnaire peut être visualisée par la commande 19.

20> put(aa, hello).
worked
21> Z = test1:demo(2).
!!! Error in process <0.17.0> with exit value:
{{badmatch,1},{test1,demo,[2]}}
** exited: {{badmatch,1},{test1,demo,[2]}} **
      

Les commandes 20 et 21 remettent la valeur de l'objet aa du dictionnaire a hello et appellent test1:demo(2). L'évaluation échoue et les modifications apportées au dictionnaire, avant que l'erreur ne survienne, sont supprimées.

22> Z.
** exited: {{unbound,'Z'},{erl_eval,expr,3}} **
23> get(aa).
hello
      

Les commandes 22 et 23 montrent que Z n'était pas liée à une valeur et que l'objet aa du dictionnaire a conservé sa valeur initial.

24> erase(), put(aa, hello).
undefined.
25> spawn(test1, demo, [1]).
<0.15.1>
26> get(aa).
hello
      

Les commandes 24, 25 et 26 montrent l'effet de l'évaluation de test1:demo(1) en arrière plan. Dans ce cas l'expression est évaluée dans un nouvel "évaluateur" créé pour l'occasion et toutes les modifications faites dans le dictionnaire du process sont locales à ce nouveau process et par conséquent ne sont pas visibles par le shell.

27> io:format("hello hello\n").
hello hello
ok
28> e(27).
hello hello
ok
29> v(27).
ok
      

Les commandes 27, 28 et 29 utilisent les fonctionnalités d'historique du shell. La commande 28 e(27), ré-évalue la commande 27. La commande 29 v(27) utilise la valeur (résultat) de la commande 27. Dans le cas d'une fonction "pure", c'est a dire une fonction sans effet de bord, le résultat est le meme. Pour une fonction ayant des effets de bord le résultat peut être différent.

Dans les commandes suivantes, nous utilisons le module test2 défini de la manière suivante:

-module (test2).
-export ([loop/1]).

loop(N) ->
io:format('Hello Number:~w\n', [N]),
loop(N+1).
      

Compilez le par c(test2). et continuez avec la commande 30.

30> test2:loop(0).
Hello Number:1
Hello Number:2
Hello Number:3
Hello Number:4
Hello Number:5
User switch command
-->
      

La commande 30 évalue test2:loop(0), qui met le systeme dans une boucle infinie. L'utilisateur a tapé Control G. Cela suspend les sorties du process courant, qui boucle, et entre en mode JCL. En mode JCL vous pouvez démarrer et stopper les travaux.

Tapez q pour quitter le shell Erlang, puis ouvrez un nouveau shell et essayez les commandes suivantes:

1> F = fun(X) -> 2*X end.
#Fun<erl_eval>
2> F(2).
4
      

La commande 1 associe la variable F à une fun, et la commande 2 évalue l'expresion F(2).

1.3.4 Utilisation Avancée du Shell - Mode Job Control

Quand le shell démarre, il lance un unique process "évaluateur". Ce process, ainsi tout les process locaux, qu'il crée (essaime) sont appelé des jobs . Seul le job courant qui est dit connecté (Connected), peu effectuer des opérations utilisant les I/O standards. Tous les autres process sont dit detachés et seront bloqués s'ils tentent d'utiliser les I/O standards. Les jobs n'utilisant pas ces I/O standards continuerons normallement.

Lorsque l'utilisateur tape Control G le job courrant est détaché, et le shell entre en mode JCL. L'invite change et ressemble à:

-->
      

En tapant ? un message d'aide apparait:

--> ?
c [nn]   - connect to the current job
i [nn]   - interrupt job
k [nn]   - kill job
j        - list all jobs
s        - start new job
r [node] - start a remote shell
q        - quit erlang
? | h    - help
      

Les commandes JCL ont le comportement suivant.

Commande Fonction
c Connexion au job courrant. Le shell standard sera repris. Les opérations utilisant les I/O standard seront intercalées avec les entrées de l'utilisateur dans le shell.
c [nn] Comme ci-dessus mais pour le job nn.
k Tue le job courrant. Tout les process créés dans ce job seront tués a la condition qu'ils n'aient pas évalué la primitive group_leader/2, et qu'ils sont situés en sur la machine local. Les process créés sur des noeuds distants ne seront pas tués.
k [nn] Comme précédement mais pour le job nn.
j Liste tout les jobs. Une liste de tout les jobs connus est affichée. Le job courrant est préfixé par `*'.
s Start a new job. This will be assigned a new index [nn], which can be used for referencing.
r [node] Démare un job sur un noeud distant. Ceci est utilisé en mode distribué pour permettre a un shell tournant sur un noeud de controler d'autres applications tournant sur un réseau de noeuds.
q Quitte Erlang/OTP.
? | h Aide.
Les commandes en mode JCL

1.4 Compilation

Un fichier est compilé par l'évaluation de la fonction

compile:file(File, Options).
    

File est le nom du fichier, et Options est une liste d'options du compilateur. Consultez le Manuel de Référence pour une liste complete de ces Options.

Vous pouvez aussi entrer la commande c(File) depuis le shell Erlang. Cette commande suppose que les conditions suivantes sont réunies

  1. Le nom du module est le même que le nom du fichier sans l'extension .erl.

  2. Le code est chargé immédiatement si la compilation réussie.

La fonction make:all() peut être utilisé pour compiler plusieurs fichiers. Tout les fichiers doivent être situés dans le même répertoire. Consultez le Manuel de Référence, fonction make(3) pour plus de détails.

1.4.1 Message du compilateurs

Le compilateur Erlang détecte un certain nombre d'erreurs. Cela peut être:

  • des erreurs de syntaxe

  • des erreurs de variables

  • des fonctions manquantes.

Le compilateur prévient aussi lors d'erreurs potentiels.

1.4.1.1 Erreurs de syntaxe

Les erreurs de syntaxes sont signalées pour du code Erlang syntaxiquement incorrect. Par exemple, la partie de code suivante est incorrecte et déclenchera un message de la part du compilateur:

test(X, Y) ->
    case g(X) o
        Y -> 1;
        2 -> 2
    end.
        

Le mot clé of dans cette instruction case est incorrectement rédigé. Le compilateur produit ce diagnostique:

test1.erl: 10 : of expected before `o'
        

Cela signifie qu'une erreur est survenue en ligne 10 du fichier test1.erl. Le message qui suit le numéro de ligne décrit l'erreur.

1.4.1.2 Erreurs sur les Variables

Deux types d'erreurs sur les variables peuvent être détectées par le compilateur. Les variables peuvent être undefined (indéfinies), ou unsafe. Dans l'exemple suivant, les variables Y et Z sont indéfinies:

test(X) ->
    A = f(X, Y, Z),
    b(A, X).
        

A la compilation, le messages d'erreur suivant est affiché:

./test.erl:11: variable 'Y' is unbound
/test.erl:11: variable 'Z' is unbound
        

La raison de ces erreurs est que les variables Y et Z ne sont pas définies.

L'exemple suivant montre l'utilisation de variable peu sur (unsafe):

test1(X) ->
    case f(X) of
        true -> Y = 1, Z = 2;
        false -> Y = 2
    end,
    g(Y, Z).
        

Dans cet exemple, il y a deux branches d'exécution possible dans le bloc case. Dans un de ces cas les variables Y et Z sont affectées, dans l'autre cas seul la variable Y est affectée. Après le bloc case, nous pouvons être seulement certain que la variable Y est affectée et la variable Z est dite unsafe. Par la suite toute utilisation de Z déclenchera un message d'erreur. Dans ce cas le message suivant sera généré par le compilateur:

./test1.erl:9: variable 'Z' is unsafe
        

Si aucune référence n'est faite à Z après le bloc case, la fonction est correcte comme le montre cet exemple:

test2(X) ->
    case f(X) of
        true -> Y = 1, Z = 2;
        false -> Y = 2
    end,
    g(Y).
        

Pour les deux fonctions test1 et test2 ci-dessus, le compilateur affichera un avertissement:

./test1.erl:9: Warning: variable 'Y' exported from ['case']
        

Pour éviter ce message et diminuer le risque de variable unsafe, il est préférable d'écrire le code comme suit:

test3(X) ->
    Y = case f(X) of
            true -> 1;
            false -> 2
        end,
    g(Y).
        
1.4.1.3 Fonctions Manquantes

Le module suivant contient une fonction manquante:

-module(test).
-export([test/1]).
test(X) -> try(X, abc).
        

Quand le module est compilé, le résultat est:

> c(test).
/test.erl:3: function try/2 undefined
error
        

1.5 Debuggage avec le gestionnaire de Process

Le gestionnaire de process pman, est un outil qui trace l'évaluation du code. Il est capable de tracer plusieurs process différents, et plusieurs machines différentes si un système distribué est utilisé. pman est controlé à travers une inteface graphique simple.

Démarré pman comme suit:

  • lancer la fonction pman:start() depuis le shell Erlang, ou

  • cliquer sur le bouton pman de la barre d'outils.

La fenêtre suivante est affiché au démarrage de pman:

starterl_fig5
L'interface de Pman

Cette section décrit une session de debuggage simple, utilisant le traçage du code d'un process unique.

Pour une description plus détaillée de pman voir le Guide de l'Utilisateur du Gestionnaire de Process.

1.5.1 Exemple

Nous illustrerons cette exemple en traçant l'évaluation de la fonction ping_pong:ping, dont voici la définition:

-module(ping_pong).
-export([ping/0, pong/0]).

ping() ->
    Pong = spawn(ping_pong, pong, []),
    Pong ! {self(), ping},
    receive
        pong ->
            pong
    end.

pong() ->
    receive
        {Ping, ping} ->
            Ping ! pong
    end.
      

Pour tracer le process, suivez ces opérations:

  1. Compilez le module.

  2. Selectionnez l'option Shell Process dans le menu Trace de la fenêtre de Pman. La fenêtre suivante est affichée. La fenêtre de trace du shell

  3. Depuis la fenêtre du shell de "traçage" sélectionnez le choix Options... dans le menuFile. Assurez vous que les choix Trace send at Trace receive soient bien sélectionnés et cliquez sur OK.

  4. Evaluez la fonction ping_pong:ping().
    2> ping_pong:ping().
    pong.
              

  5. Le contenu de la fenêtre de trace change pour afficher la liste des fonctions appelées. Trace de la fonction ping_pong:ping().

starterl_fig6
La fenêtre de trace du shell

starterl_fig7
Trace de la fonction ping_pong:ping()

1.6 Erlang Distribué

Erlang peut être utilisé pour écrire des applications distribuées, qui tournent simultanément sur plusieurs ordinateurs. La programmation distribuée avec Erlang est le sujet du livre Concurrent Programming in ERLANG. Consultez aussi le Manuel de Référence.

1.6.1 Noeuds

Le noeud est le concept de base d'Erlang distribué. Dans un système Erlang distribué, le terme de noeud désigne un moteur d'exécution (runtime system) Erlang, qui peut communiquer avec les autres systèmes Erlang. A chaque noeud est associé un nom, qui est retourné par la fonction de base node(). Ce nom est un atome et son unicité est garantie. Le format de ce nom peut varier d'une implémentation d'Erlang a une autre, mais c'est toujours un atome constitué de deux parties séparées par le caractère @. En voici un exemple:

dilbert@super.du.ericsson.se
      

Avant de pouvoir comprendre la structure d'un nom de noeud, il est nécessaire de connaitre comment les noms des hôtes sont constitués.

1.6.1.1 Noms des Hôtes

Tous les hôtes, connectés au réseau, ont un numéro IP. Il n'est pas très pratique d'utiliser cette adresse IP pour désigner les hôtes car ils sont constitués d'une série de chiffres et qu'il est difficile de s'en rappeler. Pour cette raison, des noms sont donnés aux hôtes.

Le nom des hôtes, connectés à Internet, sont organisés en domaines. Les domaines sont constitués hiérachiquement, avec un domaine "haut niveau" et des "sous-domaines". Par exemple, le domaine denommé du.etx.ericsson.se est un sous domaine, faisant partie d'un autre sous domaines etx.ericsson.se, qui est lui même une partie du domaine se.

Lorsqu'il n'y a pas d'ambiguité possible sur le dommaine d'appartenance d'un hôte, il n'est pas nécessaire d'utiliser un nom complet. Dans l'exemple super.du.ext.ericsson.se, la premiere partie "super" suffira. On dit alors que "super" est le nom court de l'hôte (short host name).

Les hôtes qui ne sont pas connectés à Internet et n'appartiennent pas à un domaine particulier, seront simplement appelé par leur nom court, "super" par exemple.

Nous utilisons le terme de nom de l'hôte pour désigner le nom des hôtes. C'est le contexte qui précisera si cela sigifie le nom long ou court.

1.6.1.2 Noms des Noeuds

Un nom de noeud Erlang est un atome construit par la concaténation d'un nom fourni par l'utilisateur, du caractère @, et du nom de l'hôte sur lequel le système Erlang est exécuté. Par exemple:

dilbert@super.du.etx.ericsson.se
        

Dans cet exemple, "dilbert" est le nom du noeud Erlang, et "super.du.etx.ericsson.se" est le nom de l'hôte sur lequel tourne Erlang.

Erlang distribué exige que les noms d'hôtes soient unique, puisque les noeuds Erlang s'identifient entre eux par les noms de noeuds. Nous pouvons nous assurer de l'unicité des noms des hôtes soit en utilisant des noms longs, soit en utilisant des noms courts avec la condition supplémentaire que les hôtes appartiennent au même domaine (ou que le réseau n'est pas connecté à Internet).

Lorsque des noms long sont utilisés pour les hôtes, les noms de noeuds correspondant sont dit noms de noeud long. Par exemple:

dilbert@super.du.etx.ericsson.se
        

Dans ce cas, Erlang est démarré avec l'option -name. Le systeme vérifie que le nom de l'hôte, contenu dans le nom du noeud, contienne au moins un point (.). Sinon, le nom de l'hôte est considéré comme erroné.

De même, lors de l'utilisation de nom court pour les hôtes, les noms de noeuds correpondant sont appelé noms de noeud courts. Par exemple:

dilbert@super
        

Dans ce cas Erlang est démarré avec l'option -sname.

Note!

Un Erlang démarré avec des noms de noeud longs ne peut pas communiquer avec un noeud démarré en utilisant un nom court.

Le plus souvent, le contexte permet de savoir si le nom de noeud est long ou court. Dans ce cas, nous utilisons le terme nom de noeud sans préciser s'il est long ou court.

La première partie du nom de noeud qui est placée avant le caractère @ est le nom simple du noeud. Le nom simple d'un noeud est unique par rapport a l'hôte sur lequel il tourne. Au lancement d'Erlang avec les options -name ou -sname, le nom simple est donné par l'utilisateur. L'autre partie du nom de noeud, le nom de l'hôte, est ajouter par le système Erlang au démarrage.

1.6.2 Démarrage

Exécutez la commande suivante pour démarrer un noeud Erlang distribué:

% erl -name foobar
Eshell V4.4 (abort with ^G)
(foobar@super.eua.ericsson.se)1>
      

Le nom du noeud affiché par le système, inclu le nom de l'hôte. Une autre façon de faire est de démarrer le système avec l'option -sname. C'est parfois la seule manière de lancer un noeud Erlang distribué si le serveur de nom de domaine (DNS) ne fonctionne pas ou n'est pas disponible.

1.6.3 Options du Script pour la Distribution

Le script exécutable erl démarre le moteur d'exécution d'Erlang. Consultez le Manuel de Référence, erl(1) pour une liste complète des options qui peuvent être utilisées au lancement du srcipt. Cette section décrit certaines options controlant l'aspect distribution:

  • -name Name
    Cette option fait d'un noeud un noeud distribué. Il contacte tout les serveurs reseau nécessaire pour créer un noeud distribué. Référez vous au Manuel de Référence, net_kernel(3) pour plus de détails. Le nom du noeud sera Name@Host, ou Host est le nom complet de l'hôte courant. Cette option veillera a ce que le démon de gestion des ports d'Erlang (epmd) tourne sur l'hôte courant avant qu'Erlang ne soit démarré. Consultez le Manuel de Référence, epmd(3).

  • -sname Name
    Cette option est la même que -name, sauf pour le nom d'hôte utilisé. Le nom du noeud sera Name@Host, Host étant le nom court de l'hôte. Si le serveur de nom de domaine (DNS) ne fonctionne pas, c'est parfois la seul façon de lancer Erlang distribué. L'option -sname ne permet pas de communiquer avec des systemes utilisant l'option -name car les noms de noeud doivent être unique en Erlang.

  • -setcookie Cookie
    Cette option positionne le magic cookie du noeud courant à Cookie. Puisque erlang:set_cookie(node(), Cookie) est utilisé, tous les autres noeuds doivent avoir leur cookies positionné à Cookie aussi. De cette manière, plusieurs noeuds peuvent partager le même magic cookie (voir la section suivante Sécurité).

  • -connect_all false
    Cette option rend le graphe de connexion du noeud plus «léger» (ou plus «maigre»). Seule les connexions directes sont établies.

1.6.4 Sécurité

Les noeuds Erlang sont protégés par un systeme de magic cookie. Consultez le Manuel de Référence, a la section kernel, de auth (3) pour plus d'informations sur le système magic cookies.

  1. Quand un message est envoyé d'un noeud à un autre, le noeud émetteur attache le magic cookie du noeud destinataire au message.

  2. Le moteur d'exécution sur le noeud destinataire vérifie que le magic cookie est valide pour ce noeud.

  3. Si le magic cookie est correcte, le message est accepté. Sinon le message est traité de la manière suivante:
    • Le message est transformé en message à "badcookie".

    • Ce dernier est envoyé au process systeme net_kernel.

    • Par défaut, net_kernel passe le message au process auth.

    • Ce process auth est alors chargé d'effectuer l'opération appropriée pour les messages non autorisés. Dans le système standard, l'action par défaut est de couper la connexion avec le noeud expéditeur.


Les magic cookies sont assignés aux noeuds de la façon suivante:

  1. Initialement, à chaque noeud est assigné un atome aléatoire comme magic cookie, et chaque noeud utilise l'atome nocookie pour les autres noeuds.

  2. Quand le serveur standard auth est démarré sans l'option -setcookie, il lit un fichier nommé $HOME/.erlang.cookie. Si le fichier $HOME/.erlang.cookie n'existe pas, il est créé et contient une chaîne aléatoire. Les permissions de ce fichier sont positionnées à lecture seule pour le propriétaire.

  3. Le système crée un atome à partir du contenu de ce fichier et la fonction erlang:set_cookie(node(),CookieAtom) positionne le magic cookie du noeud à la valeur de cet atome.

Un noeud Erlang fonctionne sans aucune protection quand erlang:set_cookie(node(), nocookie) est utilisé. Cela peut être approprié dans certains cas pour les systemes qui ne sont pas connectés à un réseau, ou pour des systemes utilisés uniquement pour la maintenance. Consultez le Manuel de Référence, auth(3) pour plus de détails à propos du système de sécurité.

1.6.5 Noeuds Esclaves

Le module slave de la librairie d'Erlang/OTP fourni des fonctionnalités pour démarrer et controler des noeuds esclaves. Ces fonctionalités sont spécifiques à Unix.

Les noeuds distants sont démarrés à l'aide des commandes Unix rsh. Cependant, pour utiliser ces commandes, l'utilisateur ne doit pas seulement utiliser un systeme Unix, mais doit aussi les droits suffisant pour ne pas avoir à saisir un mot de passe pour l'utilisation de rsh.

Referez vous aux manuels suivant pour des informations complémentaires:

  • La documentation Unix, rsh(1)

  • Le Manuel de Référence, slave(3).

1.7 Configuration

Le système standard Erlang/OTP peut être reconfiguré pour modifier les comportements par défaut au démarrage.

1.7.1 Le Fichier .erlang

Au démarrage d'Erlang/OTP le système cherche un fichier nommé .erlang dans le répertoire depuis lequel Erlang est lancé. S'il n'existe pas, il est recherché dans le répertoire personnel de l'utilisateur.

Si un fichier .erlang est trouvé, il doit contenir des expressions Erlang valides. Ces expressions sont évaluées comme si elles étaient saisies dans le shell.

Un fichier .erlang type contient un ensemble de chemin de recherche, par exemple:

io:format("executing user profile in HOME/.erlang\n",[]).
code:add_path("/home/calvin/test/ebin").
code:add_path("/home/hobbes/bigappl-1.2/ebin").
io:format(".erlang rc finished\n",[]).
      

1.7.2 user_default et shell_default

Les fonctions dans le shell qui ne sont pas préfixées par un nom de module sont considérées comme des objets fonctions (Fun), des fonctions de base (built-in), ou appartenant au module user_default ou shell_default.

Pour inclure des commandes shell privées, définissez les dans un module user_default et ajoutez l'argument suivant sur la première ligne du fichier .erlang.

code:load_abs("..../user_default").
      

1.7.3 erl

Si le contenu de .erlang est modifié et qu'une version privée de user_default est défini, il est possible de personnaliser l'environnement d'Erlang/OTP. Des modifications plus importantes peuvent être faites en fournissants des arguments au script de démarrage erl. Consultez le Manuel de référence erl(1) et init(3) pour plus d'informations.


Copyright © 1991-2001 Ericsson Utvecklings AB

Pour tout commentaire: erlang@erlang-fr.org

Dernière modification: 2005-11-11 18:47:49