mercredi 30 septembre 2009

Erlang : guide de survie : Le démarrage

Bon voici le récit de mes premiers essais avec Erlang.
Après un échec cuisant avec Haskell pour sortir quelques lignes de code, je refais une tentative avec Erlang.

1) Le lancement du shell : erl , puis crtl-g pour passer en mode JCL (lancer ou arrêter les processus)

2) Lancement du menu graphique depuis le shell erl : toolbar:start().
Chaque instruction se termine par un '.' (point).

3) Compilation dans le shell : c(nom_du_programme). ou en ligne de commande
erlc . On obtient des fichiers avec l'extension 'beam'.
Très vite il est nécessaire de se creer un Makefile pour automatiser la compilation. Il existe un automake qui permet de génerer des squelettes pour des projets avec OTP (Open Telecom Platform).
Exemple de mon Makefile de base :

# leave these lines alone
.SUFFIXES: .erl .beam .yrl

.erl.beam:
erlc -W $<

.yrl.erl:
erlc -W $<

ERL = erl -boot start_clean

# Here's a list of the erlang modules you want compiling
# If the modules don't fit onto one line add a \ character
# to the end of the line and continue on the next line

# Edit the lines below
MODS = fileinfo truncate

# The first target in any makefile is the default target.
# If you just type "make" then "make all" is assumed (because
# "all" is the first target in this makefile)

all: compile

compile: ${MODS:%=%.beam}

## special compilation requirements are added here


## run an application from the makefile
run:
erl -noshell -s truncate main /root/Desktop/Lost.last.mkv

# remove all the code

clean:
rm -rf *.beam erl_crash.dump






L'entrée 'run' permet de lancer le programme avec les bonnes options pour éviter les saisies fastidieuses.

4) Le lancement en ligne de commande d'un programme:

erl -noshell -s nom_du_module fonction_du module parametre

Un programme lancé de cette façon ne s'arrête jamais , il faut ajouter un exit ou encore mieux : un init:stop(). Si le programme lance des processus par spawn, l'arret du processus père met fin aux processus fils.

5) Pour envoyer un message sur la console l'équivalent d'un print "coucou" se fait par l'instruction io:format("coucou",[]) , un peu comme l'instruction printf en C. Les règles de formatage sont plus réduites qu'en C:
'~s' pour une chaîne de caractère
'~w' pour un type quelconque (entier ,chaine,tuple)
'~p' pour une présentation en ligne.
'~f' nombre
La syntaxe est longueur.precision.padding

Exemple: ~10.2.0f donne : longeur totale 10 , 2 chiffres après la virgule et des '0' en complement.
Le '~n' donne un retour charriot '\n'.

Pour formater une variable au moment de l'assignation:
T= io_lib:format("le texte est ~w",['"ci"]).

Autre exemple: charge des entiers sur 2 caracteres, avec 0 en tête.
Texte= lists:flatten( io_lib:format("~2..0w",[I])),

6) Structure d'un programme .
Si la résolution d'un probleme peut se faire de manière linéaire , il ne sert à rien de le faire en Erlang. Par contre si on désire faire travailler plusieurs processus en même temps (concurrent) , l'Erlang est le langage qui est fait pour ca.
L'unité de base est le module , le module regroupe des fonctions. On peut classifier les fonctions en 3 catégories
- Les fonctions autonomes qui réalisent des traitements
- Des fonctions de supervision, qui lancent et gèrent les fonctions autonomes
- Les fonctions qui charpentent le programme et les données (gestion de la configuration, accès aux structures).

il est recommandé d'organiser le code en trois groupes:
- Les fichiers d'entete (hrl , comme les fichiers header en C) .
- Un fichier par module , un module par fonctions connexes
- Un fichier regroupant les fonctions d'intendance et le superviseur.
exemple :

-module (truncate).
-export([main/1,console/1,launcher/2]).
-define(GO2OCTET, 1073741824). %ratio de conversion
-define(TRUNK, 104857600). % taille de morceaux
-define(MOTIF, "trunk_%%.mkv"). % nom en sortie
-include("structures.hrl").


Dans l'ordre : le nom du module , les fonctions que le module expose (exporte) , la définition de quelques macros, l'include vers les fichiers headers. On trouvera rarement des clauses d'import. Il suffit d'appleler autre_module:fonction() pour que le compilateur recherche autre_module.beam.

7) Les structures de données
Comme en C, il est possible de manipuler des 'record'. Ces structures permettent de manipuler des données organisées.
Exemple :

%% La description dun segment
-record(segment,{nom,debut,longueur}).
create_segment(Nom,Debut,Longueur)->
#segment{nom = Nom,
debut=Debut,
longueur=Longueur}.


Le fichier contient la description de la structure et les fonctions pour la manipuler (create_ ou new ou foobar) .

Pour retrouver les données :

Nom_segment =H#segment.nom ,
Debut_segment =H#segment.debut,
Longueur_segment =H#segment.longueur,



8) Un exemple de procédure complète

main([A]) ->
%recuperation de la ligne de commande
Nom_fichier = atom_to_list(A),
Tailleoctet= fileinfo:file_size_and_type(Nom_fichier),
Taille= round (Tailleoctet/ ?GO2OCTET * 100)/100,
io:format("Taille du fichier:~p Go~n",[Taille]),
io:format("Trunk ~p Octets~n",[?TRUNK]),
%preparation du nombre de morceaux et de leur taille
Morceaux= fileinfo:decoupe(Tailleoctet,round(?TRUNK),0,0,"eric%%.mkv",[]),
io:format("Result ~p~n",[Morceaux]),
% lancement des decoupages
launcher(Morceaux,Nom_fichier). % lancement processus qui vont decouper le fichier

% init:stop().
%% donc le programme ne s arrete jamais !!

9) détail du lanceur


launcher([],Nom) -> ok;
launcher([H|Reste],Nom) -> Nom_segment =H#segment.nom ,
Debut_segment =H#segment.debut,
Longueur_segment=H#segment.longueur,
io:format("Lancement de ~p debut ~p longueur ~p~n",[Nom_segment,Debut_segment,Longueur_segment]),
spawn(fileinfo,create_segment,[Nom,Nom_segment,Debut_segment,Longueur_segment]),
launcher(Reste,Nom).



La procédure est récursive, la premiere ligne est le cas trivial :
launcher([],Nom) -> ok;
La liste est vide , je n'ai plus rien à lancer.




10) Les pages d'aide.

erl -man NOM_De_LA_PAGE

exemples :
erl -man Erlang (% donne le détails des BIFS Build In Function)
erl -man io
erl -man file

Il reste à voir :
-Le mode debug
-L'écriture d'un vrai superviseur
-Le dalogue entre le superviseur et les processus travailleurs

lundi 21 septembre 2009

Le libre l'avenir du web (musique) ?


Apres Radiohead , le groupe de rock Smashing Pumpkins vient d'offrir aux Internautes leur dernier album à telecharger gratuitement. Comment dans ce cas vont ils gagner de l'argent ?. Simplement en proposant une version CD/DVD bourrée de bonus et de très bonne qualité.
Le libre est il l'avenir de la musique et du WEB ?. Les études revelent que les plus gros telechargeurs sont aussi les plus gros acheteurs de produits culturels . Cela reste des sondages. Quand on interroge des amis , une grosse majorité regarde plus Arte ou Thalassa que les grosses daubes de TF1. Il y aurait donc deux types de telechargeurs: ceux qui telechargent sans scrupules et les autres qui compensent volontairement ou non par des achats réguliers.

Un modèle economique se dessine pour la musique: Libre et gratuite sur Internet avec une rémuneration pour par le biais des collectors et des concerts. Par contre pour le cinéma l'équation est plus dure à résoudre, d'autant qu'avec les dernieres nouveautés, il est possible d'avoir une qualité cinema à la maison avec en plus l'avantage de pouvoir régler le volume sonore (les cinemas abusent de leurs installations).

En attendant en avant la musique.


mardi 15 septembre 2009

Bienvenue chez Erlang


J'ai attrapé des migraines en essayant de comprendre les principes de la programmation fonctionnelle avec Haskell. Pour la première fois je n'ai pas réussi à écrire un petit programme de démonstration avec un nouveau langage.

Je me suis rabattu sur Erlang et là , la lumière à jaillie ! J'ai compris les grands principes d'Erlang grâce à mes lectures sur Haskell.

Erlang est un langage fonctionnel 'allégé' avec beaucoup moins de contrainte qu' Haskell mais aussi moins de richesse au niveau du traitement récursif (exemple: les opérations de map/fold par la gauche ou à droite).

Les grands principes d'Erlang

Erlang est orienté 'concurrent' . Il faut traduire le terme par processus 'partenaires'.

Quand on a faire à un traitement lourd , il y a plusieurs solutions :
  1. La plus couteuse: Utiliser une énorme machine avec un énorme CPU : cette solution est passée de mode.
  2. Lancer plusieurs petits programmes pour traiterle même problème:
Là on en encore 3 possibilités :

  • Technique du Fork.
On peut utiliser la technique du Fork présente sur les machines Unix. Le processus père est dupliqué en processus fils. Tout l'environnement du père est ainsi cloné dont les descripteurs de fichier. Il n'y a souvent qu'un seul programme qui doit faire le test suivant: je suis le père ou je suis un des fils. On trouvera ainsi dans le code des paragraphes de libération de ressources qui ne seront activés que dans l'environnement d'un processus fils. Il faudra aussi gérer la communication inter-processus par l'utilisation de sémaphore ou des tubes nommés.

  • Les Threads.
Les threads partagent un espace de mémoire commun et peuvent ainsi échanger des informations. Par contre , il faut utiliser des rtechniques de synchronisation et de verrouillage de memoire.

  • Par message
Erlang utilise des messages pour communiquer entre les processus , comme on peut le faire avec notre client de messagerie. On ne parle plus de thread mais de processus. Chaque processus à son propre espace d'adressage. Chaque processus possède une boite au lettre et est capable de recevoir ou d'envoyer des messages dans un protocole propre à Erlang. Cette gestion est facilitée par l'utilisation des principes de la programmation fonctionnelle .

Ainsi Erlang est capable de lancer et de superviser plusieurs precessus en local MAIS aussi en mode distant sur des machines distinctes.

Les principes de la programmation fonctionnelle dans Erlang.

  • Les variables.

Les variables sont immuables : Il est possible d'assigner une variables mais on ne peut pas la modififer (SANS qu'on puisse parler de constante.) Question : comment incrémenter une variable ?

  • Les fonctions
Un programme est une suite de fonction. Chaque fonction est protégée par un filtre (motif ou condition) qui permet ou non de rentrer dans certaines parties de la fonction .

  • La récursivité.

Un programmeur habitué à ses boucles FOR , WHILE ne trouvera pas directement les équivalences. C'est d'ailleurs peut etre une erreur de conception que d'avoir à faire une boucle de type classique.

Les livres

En francais Lien vers Eyrolles

En Anglais : La bible Erlang

lundi 14 septembre 2009

S'envoyer en l'air dans la rue


Pour cela, il faut chausser une paire d'échasse urbaine. Formée d'une longue tige flexible en fibre élastique, équipée d'un repose pied.

Il ne faut pas plus de 3 minutes pour maitriser l'engin. La difficulté réside dans ces deux points:
* Il n'est pas possible de resté immobile, il faut en permanence piétiner pour rester en équilibre.
* Il faut inverser les mécanismes naturels de compensation : Quand on perd l'équilibre: il faut se dresser au lieu de s'accroupir.

Il est possible de courir à 40 Km (à vérifier) . Les échasses compensent 10 fois plus que les membres inférieurs et donc il n'y pas de risques de problèmes articulaires mais gare à la chute.

20090829-_aaj0842n