26-04-2012, 02:05 PM
(Modification du message : 26-04-2012, 02:06 PM par Sephi-Chan.)
Bon, je me remets un peu sur Erlang ces jours-ci.
J'en profite pour parler du système de processus.
Le processus a l'air d'être l'unité de base de Erlang : un programme est composé de multiples processus qui communiquent entre eux par des messages.
Contrairement à la programmation objet, on n'invoque pas de méthode sur un processus : on lui envoie un message. La différence, c'est qu'un n'implique pas forcément un retour. Si je veux savoir si le processus en face a entendu mon message, il faut qu'il me réponde (en m'envoyant à son tour un message).
Le parallèle avec la vie réelle est assez simple : chaque personne est un processus. Quand on s'adresse à quelqu'un (un processus), on lui envoie un message auquel il répond ou non (parce qu'il n'a pas entendu ou qu'il est mort entre-temps, par exemple). Quand il répond, il envoie à son tour un message.
On peut créer un processus grâce à la fonction
J'utilise ici cette fonction
Je crée donc un processus à partir de la fonction
Voyons une implémentation possible de ce module et de cette fonction.
Ici,
En l'état, elle est capable de recevoir deux types de messages : un message contenant seulement l'atom
Comme on peut le voir, le premier cas de message affiche à l'écran une chaîne puis appelle la fonction
À l'inverse, c'est exactement le comportement qu'on demande à l'autre forme de message reçu : l'arrêt de la réception.
Je teste maintenant le code dans une console :
Comme on peut le voir, quand j'envoie un message contenant l'atom
Notons que l'utilisation de la fonction
Dans le prochain poste, j'expliquerais comment permettre à notre personnage de répondre au message.
J'en profite pour parler du système de processus.
Le processus a l'air d'être l'unité de base de Erlang : un programme est composé de multiples processus qui communiquent entre eux par des messages.
Contrairement à la programmation objet, on n'invoque pas de méthode sur un processus : on lui envoie un message. La différence, c'est qu'un n'implique pas forcément un retour. Si je veux savoir si le processus en face a entendu mon message, il faut qu'il me réponde (en m'envoyant à son tour un message).
Le parallèle avec la vie réelle est assez simple : chaque personne est un processus. Quand on s'adresse à quelqu'un (un processus), on lui envoie un message auquel il répond ou non (parce qu'il n'a pas entendu ou qu'il est mort entre-temps, par exemple). Quand il répond, il envoie à son tour un message.
On peut créer un processus grâce à la fonction
spawn
.
Character = spawn(character, character, []).
J'utilise ici cette fonction
spawn
avec 3 arguments, le premier est un atom qui indique le nom du module, le second est un atom qui indique le nom de la fonction, et le troisième est une liste d'arguments à passer à la fonction.Je crée donc un processus à partir de la fonction
character
du module character
. Je ne lui donne aucun argument. La fonction me retourne un l'identifiant du processus créé (qu'on appelle Pid, pour process identifier) que je garde de côté dans une variable Character
, qu'on distingue d'un atom par la majuscule) pour pouvoir lui envoyer des messages.Voyons une implémentation possible de ce module et de cette fonction.
- module(character).
- export([ character/0 ]).
character() ->
receive
introduce ->
io:format("Received introduce message.~n"),
character();
Any ->
io:format("Received other kind of message. Stop listening.~n"),
void
end.
Ici,
character
est une fonction qui dispose d'une clause receive
, qui va lui permettre de recevoir des messages et qui utilise le pattern matching pour distinguer les messages qu'elle reçoit et les traiter.En l'état, elle est capable de recevoir deux types de messages : un message contenant seulement l'atom
introduce
, et n'importe quel autre message (on stock ce message — quel qu'il soit — dans la variable Any, qui aurait pu s'appeler n'importe comment, par ailleurs).Comme on peut le voir, le premier cas de message affiche à l'écran une chaîne puis appelle la fonction
character
: elle est donc récursive. Si on ne fait pas ça, le bloc receive se termine et le processus n'est plus capable de recevoir de message.À l'inverse, c'est exactement le comportement qu'on demande à l'autre forme de message reçu : l'arrêt de la réception.
Je teste maintenant le code dans une console :
3> c(character).
character.erl:20: Warning: variable 'Any' is unused
{ok,character}
4> Character = spawn(character, character, []).
<0.41.0>
5> Character ! introduce.
Received introduce message.
introduce
6> Character ! introduce.
Received introduce message.
introduce
7> Character ! endive.
Received other kind of message. Stop listening.
endive
8> Character ! introduce.
introduce
Comme on peut le voir, quand j'envoie un message contenant l'atom
endive
, les messages introduce
suivant ne sont pas traités. Si l'on n'avait pas créé de règle pour les messages d'une autre forme, le message endive
n'aurait pas été traité, mais la réception des messages suivants n'aurait pas été interrompue pour autant (je ne suis pas encore capable d'en expliquer la raison).Notons que l'utilisation de la fonction
io:format
sert seulement pour voir facilement ce qui se passe.Dans le prochain poste, j'expliquerais comment permettre à notre personnage de répondre au message.