Affichage des articles dont le libellé est erlang. Afficher tous les articles
Affichage des articles dont le libellé est erlang. Afficher tous les articles

samedi 30 octobre 2010

Pour aller plus loin avec couchdb: la compilation

J'avais fait quelques ( posts sur le sujet) . Très vite, la manipulation de couchdb nécessite des bouts de javascript et du JSON. Je veux par exemple produire des données sous forme XML, ou proposer des vues avec des mises en page. Pour cela il faudra modifier les listes ou les vues dans couchdb.

La première précaution à prendre est de travailler avec la dernière version de couchdB. La gestion des listes et des vues a évolué d'une version à l'autre.
Pour installer une version récente de couchdb , il faudra probablement mettre à jour votre version de Erlang.


Le lancement de la commande ./configure dans l'archive de couchdb doit produire les erreurs suivantes:
La compilation de couchdb va chercher à résoudre les dépendances dont celle ci :
Is the Mozilla SpiderMonkey library installed?

spidermonkey est le moteur javascript de Firefox. Son installation complète se teste par la commande 'js' (librairie et l'interpréteur) .
Son installation se fait par:
apt-get install libmozjs-dev
Puis vient le tour de la librairie 'international character'
apt-get install libicu-dev

Enfin l'utilitaire 'curl' : c'est avec lui que se fait les premiers essais avec couchdb

apt-get install libcurl4-openssl-dev

Tout ca pour arriver au message :
configure: error: The installed Erlang version is less than 5.6.5 (R12B05).

Vous allez devoir vous payer une petite compilation du langage Erlang.

Rien de bien compliqué , juste un configure , make , make install dans le repertoire otp_src_Rnn

Puis revenir à la compilation de couchdb en précisant :
./configure --with-erlang=/usr/local/bin

Ok tout est bon le make et make install terminent l'opération. Le répertoire /usr/local/bin doit contenir au minimum erl et couchdb.





jeudi 21 octobre 2010

Ceci est un post sur la recursion dans un post sur la recursion


On distingue deux formes de récursion : La recursion directe ou indirecte.

Dans la récursion directe (exemple en ruby) la fonction s'appelle directement.

def facdir(n)
return 1 if n==1
return (n * facdir(n-1))
end


La fonction fac s'appelle en se transmettant le paremetre n-1

Dans la méthode indirecte , la fonction s'appelle aussi , mais elle va se transmettre son contexte
en plus de son parametre normal.
Pour une fonction simple , le contexte sera limité à une variable destinée à accueillir le résultat.


Exemple :


def facind_r(n,prod)
return prod if n==1
return facind_r(n-1,n*prod)
end


La variable 'prod' est le 'contexte'.

L'appel de la fonction se fera par :

def facind(n)
facind_r(n,1)
end



La méthode indirecte est meilleure que la méthode directe.
A l'appel d'une itération le système n'a pas besoin de mettre
dans la pile l'appel de la fonction CAR AUCUNE opération ne sera à réaliser à son retour.







En Haskell :


module Main where

facdir :: Int -> Int
facdir 1 = 1
facdir n = n * facdir(n-1)


facind :: Int ->Int
facind n = facind_r (n,1)

facind_r :: (Int,Int) -> Int
facind_r (1,prod) = prod
facind_r (n,prod) = facind_r( n-1, n* prod )




En Erlang:


-module (fac2).
- export([facdir/1,facind/1]).

facdir(1) -> 1;
facdir(N) -> N * facdir(N-1).

facind(N) -> facind_r(N,1).
facind_r(1,Prod) -> Prod;
facind_r(N,Prod) -> facind_r(N-1,N*Prod).


lundi 30 août 2010

#Ruby , #Erlang , #Haskell et les autres

J'ai profité de mes vacances pour lire l'ouvrage suivant:



Seven Languages in Seven Weeks: A Pragmatic Guide to Learning Programming Languages. (Lien vers l'editeur ici).

Les langages présentés sont :

IO : (lien ici) io est un langage orienté objet inspiré par smaltalk. Son originalité réside dans l'utilisation comme dans javascript d'objets basés sur les prototypes plutôt que sur des classes.
Un objet io (ou javascript) est un simple tableau associatif. Une clé du tableau peut contenir une donnée , une fonction ou une référence vers une fonction d'un prototype. L'instanciation d'un objet se fait par clonage et non pas à partir d'un modèle (template) comme dans le cas des langages basés sur les classes.

Ruby (le top du top)

Prolog.

Scala : (lien ici ) scala est un langage développé par les ingénieurs de twitter basé sur la JVM. Il permet d'utiliser les librairies Java. L'intérêt de scala est de fournir une ouverture vers les langages fonctionnels avec en plus la possibilité de mettre en place des traitements parallèles (concurrents)

Erlang. (lien ici) c'est le langage qui à mon sens permet de débuter avec les langages fonctionnels.


Clojure. (lien ici ) Ce langage est une implémentation de Lisp destinée à utiliser une JVM. Il se présente comme une évolution possible de java.

Haskell. (lien ici) Haskell est le langage fonctionnel par excellence, qui est le fruit d'un travail collectif d'un groupe de chercheurs et non pas une construction d'une personne isolée. Un bon livre de référence est

La lecture de ce livre est difficile, aussi il est possible de lire cet ouvrage collectivement sur le forum suivant: (lien ici )
Une version gratuite et commentée du livre est disponible ici.




Pour chacun de ces langages, l'auteur propose des points à approfondir sur une semaine. Et il interroge les concepteurs de ces langages sur leurs motivations et les perspectives d'évolutions. C'est un très bon livre.

Pour ceux qui sont passionnés de langage et qui veulent se lancer dans l'écriture d'un nouveau langage : le livre à avoir est :(lien ici)
Create Your Own Programming Language de Marc-André Cournoyer

A system to achieve every programmer’s dream.
Learn how to create a simple programming language in a few days with this easy step-by-step guide.

vendredi 19 mars 2010

#nosql , decisionnel et #forumdecideo

Je suis intervenu au forum decideo lien ici , cet évenement a été d'une très grande qualité et très bien organisé (philippe Nieuwbourg) . Un intervenant avant moi : renaud FINAZ de Micropole Univers a fait une intervention brillante sur l'état de l'art dans le domaine du stockage des données au sens large du terme.

Je partage son analyse dans les grandes lignes:

Le volume de stockage n'est plus un problème : le Tera est accessible à tous pour moins de 100 euros.

Le volume d'information produit pour Internet en deux ans (2009/2009) est plus important que tout le volume d'information existant (X 5)


(source http://gigaom.com/2010/03/16/northscale/)

Toute cette information est en grande partie déstructurée.

Ainsi, ce n'est plus la donnée qui fait la richesse d'une entreprise c'est sa faculté de traiter cette donnée.

Le problème des performances.

Il y a deux point de contention possibles: alimentation et l'indexation (structuration) pour la restitution.

L'alimentation.
L'alimentation d'une base de données /entrepôt à partir des différentes sources de données.
Comment intégrer, contrôler , agréger des millions de lignes de données. Actuellement ces fonctions sont traités par des programmes en mode itératifs ligne par ligne ou en mode ensembliste par des opérations portant sur un ensemble de données.

Il es possible de paralléliser les traitements à conditions mais il faut le prévoir au préalablement. Ce parallélisme est rudimentaire : j'ai N sources de données je vais les traiter par N programmes lancés en même temps. Cette méthode est naïve car elle ne fait que déplacer le problème sur le moteur de la base qui lui traite les opérations en mode file d'attente (voir page sur ACID)

Il faut donc utiliser un système d'alimentation basé sur des traitements fortement 'concurrents' qui traitent avec des bases de données qui respectent le modèle ACID mais tout en étant capable de s'affranchir du modèle file d'attente (voir le théorème de CAP) de Brewer



nosql2


Concernant les langages à utiliser.
Il n'y a pas de secret , regardons ce qui se fait chez les entreprise full web 2.0 (Facebook, twitter , amazon et google).

Les langages fonctionnels: Haskell mais surtout Erlang qui nativement est capable de travailler sur plusieurs nœuds de machine et de gérer la perte de serveur.
Scala le langage fonctionnel de twitter basé sur une JVM

Les langages hybrides: Ruby et Python

Tous ces langages possèdent des fonctions puissantes de MAP/REDUCE


L'indexation et la structuration des données.

Le calcul des agrégats ou la création des index est réalisable au moment du chargement des données ou a posteriori . Pour les agrégats et les index , il sera possible de paralléliser massivement les opérations de Map /Reduce.

Les bases à utiliser.



Tout sera fonction du type d'information à stocker .
  • Pour des restitutions de documents!: CouchDB ou mongoDB (plutot hierarchique)
  • Pour des cubes: prendre des bases orientées colonnes : cassandra, htable..

lundi 22 février 2010

Plaquettes (cheatsheet) #haskell , #uml #jquery et #ruby


J'adore les plaquettes plastifiées présentant toutes les options possibles, on peut s'en servir comme aide-mémoire, soutasse. Autant de connaissance dans un si petit volume, c'est magique.
Un site ici http://www.cheat-sheets.org/ qui centralise ces aide-memoires.

jeudi 18 février 2010

Mixer #haskell #Erlang #Java dans #Ruby

Il est possible de s'amuser à faire interagir un programme Ruby avec d'autres langages.

Avec Haskell.
Le projet Hubris se veut un pont entre ruby et Haskell. Il s'utilise en mode inline ou sous forme d'appel de module.

require 'hubris' # best line ever

class Target
hubris :inline =>"triple::Int->Int; triple n = 3*n"
end

t = Target.new
puts t.triple(10)
=> 30
Un article sur http://www.engineyard.com/blog/2010/a-hint-of-hubris/ détaille son utilisation.

Avec Erlang.

Le projet erlectricity permet de communiquer avec un process Erlang.
Le projet présente un exemple d'un simple programme de type 'echo'


require 'rubygems'
require 'erlectricity'

receive do |f|
f.when([:echo, String]) do |text|
f.send!([:result, "You said: #{text}"])
f.receive_loop
end


end

Avec du C.
(tiré de rmag numero 5)
Il faut se munir des fichiers sources Ruby . Et construire un répertoire sous la forme:

rmag/
rmag.c # source code extconf.rb # ruby file to create makefile
example.rb # a simple script to show our ext
LICENSE # license
README # some info

Le rmag.c devra commencer par la ligne magique:

#include “ruby.h”

Le fichier responsable de la création du makefile contiendra:

require 'mkmf'
ext_name = 'Rmag'
create_makefile(ext_name)


Avec Java.

Il faut utiliser la machine virtuelle Jruby et inclure le module

# This is the 'magical Java require line'.
require 'java'

A partir de là il est possible d'écrire des lignes en java.

frame = javax.swing.JFrame.new("Window") # Creating a Java JFrame
label = javax.swing.JLabel.new("Hello")


exemples à prendre sur le wiki de jruby.

jeudi 17 décembre 2009

Un bricolage sur un coin de table

DSCN0086
Un des premier prototype avec l'ancien nom : Levon et la distribution mandrake.
J'avais déja adopté un numérotation à 3 chiffres.

La mire de la version accélerateur Internet : 6 serveurs en lignes sous Debian.



Ce matin les chiffres sont tombés : 5076 utilisateurs s'étaient connectés hier sur le portail Internet de la DGFiP(ex DGCP), c'est pour nous un jalon. Ce dispositif permet aux partenaires de la DGFiP (ordonnateurs: Maires, Départements , Régions, Etablissemnts Publics) et aux agents d'accéder de manière sécurisé (certificat client) au frontal du système informatique de la DGFiP. Le composant Lemondap est la clé de voute de cet édifice, aidé par apache, Mod-Perl , Perl, memcached et openldap. C'est un reverse-proxy 'tête de pont" qui en fonction de l'URL, mandate des applications métiers. C'est un système global car il couvre les fonctionnalités allant de la délivrance des certificats clients, jusqu'à l'alimentation d'un entrepôt de données avec les log Apache. Cet entrepôt sert de base aux différentes restitutions en mode texte, graphique avec openChart et mail. L'entrepôt de données est basé sur une base PostgreSQL hébergeant des tables dénaturées préfigurant les bases de données vectorielles (voir le concept des bases vectorielles).

Ce projet est né vers 2002 , il a plusieurs branches : Lemonldap::NG (Nouvelle Gendarmerie) basé sur les Threads Perl, Un packaging Interne (basé sur une RedHat) appelé DAC, servant à la télédéclaration (7 millions d'utilisateurs).La version d'origine est là sur le cpan.org
Projet récompensé par un prix:
remiseprix_DSC_2124.jpg_w450.jpg
Je voulais remercier Arnaud, alexandre ,Casimir , le personnel des centres de Lyon, Versailles et Marseille. J'aimerais croire que dans notre nouvelle structure, un tel projet soit encore possible. Mais la réponse ne m'intéresse pas, je suis passé à autre chose. L'économie globale pour le contribuable se mesure en KE (déjà 100 ke pour la partie serveur applicatif).


Que devrait etre une nouvelle version de Lemonldap ?. Déjà le socle resterait du Debian qui est la meilleure distribution avec le meilleur système de package (elle sert de base à UBUNTU) .
Le serveur HTTP serait soit NGINX qui offre la meilleure et la plus simple API C de développement, soit un dérivé de Yaws qui est un serveur HTTP écrit en Erlang.
CouchDB remplacerait le serveur de session memcached.
La partie alimentation de l'entrepôt resterait la même (écrite en C).
Malgré mon changement d'orientation, je reste un développeur dans l'âme. Au lieu d'écrire du code , je rédige des clauses de marché , des notes. Quelque part c'est aussi de la technique. Les leviers du pouvoirs sont ailleurs, sur des terres hostiles et je dois progresser camouflé pour imposer la:

Prochain jalon: 10.000
Heureusement j'ai ce blog comme exutoire....

mercredi 18 novembre 2009

Crible d' Eratosthène en Erlang (nombres premiers)



Sur le wiki du langage GO de Google, se trouvait un exemple de proggramme qui utilisait le crible d' Eratosthène pour générer la liste des nombres premiers.

Cet exemple utilisait un chainage de filtre, le nombre à tester est injecté dans le premier filtre de la chaine. Chaque filtre teste le reste de la division de ce nombre par un nombre premier déjà trouvé. En cas d'échec, le filtre envoie le nombre à tester au filtre suivant ainsi de suite jusqu'au dernier filtre.

A la fin de ce dernier filtre, et en cas d'échec, le nombre est qualifié de premier et devient le filtre suivant en étant ajouté en bout de chaine.

La réalisation en GO commence par la création d'une fonction générateur.
Sous cette forme:

09 // Send the sequence 2, 3, 4, ... to channel 'ch'.
10 func generate(ch chan int) {
11 for i := 2; ; i++ {
12 ch <- i // Send 'i' to channel 'ch'. 13 } 14 }


Et ici une version plus élaborée:

10 func generate() chan int {
11 ch := make(chan int);
12 go func(){
13 for i := 2; ; i++ {
14 ch <- i 15 } 16 }(); 17 return ch; 18 }

En Erlang , le programme occupe plus de ligne. Il est de bonnes pratiques de scinder les programmes en composants de supervision et composants de traitement. J'ai aussi réalisé deux versions de la même fonction.
  • generator_async/3 : Cette fonction envoie en flot continu la série de nombre.
  • generator_sync/3 : Cette version n'envoie un nombre que sur demande du superviseur

Le superviseur lance le processus 'generateur' et va communiquer avec lui par un canal , comme en GO. En Erlang ou en Haskell ,les boucles for,while n'existent pas vraiment elles sont remplacées par des appels récursifs.


Le module principal superviseur:

-module (crible).
-export ([main/0,main2/0]).
loop2(Pid) ->
receive
ok -> ok;
Number -> io:format(" ~w~n",[Number]),
Pid ! next,
loop2(Pid)
end.
loop() ->
receive
ok -> ok;
Number -> io:format(" ~w~n",[Number]),
loop()

end.




main()->
_Pid =spawn(prime,generator_async,[self(),0,60000]),
loop(),
ok.
main2()->
Pid =spawn(prime,generator_sync,[self(),0,60000]),
Pid ! next ,
loop2(Pid).


Le module qui génère la suite des nombres:


-module (prime).
-export ([generator_async/3,generator_sync/3]).

generator_async(Canal,Compteur,Maximum) when Compteur == Maximum -> Canal ! ok;
generator_async(Canal,Compteur,Maximum) ->
Cpt= Compteur +1,
Canal ! Cpt,
generator_async(Canal,Cpt,Maximum).

generator_sync(Canal,Compteur,Compteur) -> Canal ! ok;
generator_sync(Canal,Compteur,Maximum) ->
Cpt= Compteur +1,
receive
next -> Canal ! Cpt ,
generator_sync(Canal,Compteur+1,Maximum)
end




J'ai utilisé ici une 'garde' dans la déclaration de fonction


generator_async(Canal,Compteur,Maximum) when Compteur == Maximum -> Canal ! ok;


C'est une condition de reconnaissance de la fonction.

Cette variante fait la même chose :

generator_sync(Canal,Compteur,Compteur) -> Canal ! ok;


Ici la variable Compteur est branchée avec le deuxième parametre d'appel de la fonction. Puis une autrre affectation de la variable Compteur est tentée avec le 3eme parametre. Si les deux valeurs sont égales le motif sera reconnu, sinon on passe à la forme d'appel suivante.

Ce système est basé sur le fait qu'il n'est pas possible de modifier le contenu d'une variable dans les langages fonctionnels.
ex : A=1 puis A=3 ou A=A+1

Pour debugger le programme en Erlang , il faut le compiler avec l'option :
erlc +debug_info

Puis lancer le shell Erlang (erl )

Sur le prompt lancer le debugger graphique par

debugger:start().


Choisir par le menu module, la liste des programmes à debugger.
Grace à ce système, il est possible de voir le contenu de messages ou l'état des variables.

Copie d'écran du debugger Erlang


Conclusion : La fonction qui utilise des echanges synchrones entre le superviseur et le composant générateur est 3 fois plus rapide que l'asynchrone.

Il est possible d'utiliser une seule ligne pour générer des séries de nombre par le système des listes "comprehensions". Ces listes injectent des données un peu à la manière de notre générateur.
Cela donnerait un ligne comme ca:

[ListePremier || Nombre <- Lists:seq(2,99999), is_prime_number(Nombre)].

Pour voir le post dans son contexte original http://germanlinux.blogspot.com/2009/11/crible-d-eratosthene-en-erlang-nombres.html

vendredi 13 novembre 2009

Go: Un nouveau langage par Google

Google communique sur son nouveau langage maison : GO.
Avant même le lancement du projet, le sujet a déclenché une polémique sur web en raison de son appellation déjà utilisée par une autre équipe:
Voir le fil de discussion ici:



Go est un langage compilé comme le C ou le C++. Il est aussi orienté traitement concurrent (dans le sens de parallélisation des traitements) comme Erlang. Ainsi les processus dialoguent entre eux par des 'Channels' ex:
chan1 <- "exemple"

Ici la chaine "exemple" est envoyée à un autre processus branché en entrée du canal "chan1"

On utilise le mot réservé 'go' pour lancer un processus , avec souvent comme paramètre le canal à brancher en entrée et en sortie :
ex:
go ma_fonction(ch_in, ch_out,un_paramètre)
Ici ma_fonction pourra lire des données à partir de ch_in et écrire des données en sortie sur ch_out

i := <-ch_in; // Receive value of new variable 'i' from 'ch_in'. ch_out <- i // Send 'i'

Les nostalgiques du Pascal retrouveront le signe ':=' qui ici permet la déclaration et le chargement d'une variable: c'est l'initialisation.

Le blog du langage go (golang) propose une illustration des processus concurrents basée sur la recherche des nombres premiers par le Crible d'Ératosthène


C'est un excellent exercice à faire en Erlgan, sur lequel je vais passer plusieurs soirées.




Le langage est fortement typé, avec des types basiques permettant de construire des structures.
Il est possible de manipuler des types originaux comme les 'channel' (type chan) et les slices : tranches de tableau. A noter qu'il n'existe que les boucles 'for' , pas de 'while' ou de 'do'.

Je suis un peu déçu de l'ensemble. Maintenant que je connais mieux les langages fonctionnels, je persiste à croire qu'il faut éviter de partager des ressources si on désire vraiment paralléliser les processus. Pour cela comme dans les langages fonctionnel il ne faut pas d'effet de bord.
Le caractère immuable des variable en Haskell ou en Erlang est très déconcertant mais c'est solution la plus simple.

Pour terminer, je suis très étonné de google sorte un nouveau langage alors que le gourou du Python est son employé. Et que dire de cette remarque relevée sur le site de Google: depuis 10 ans aucun langage ne s'est distingué.. Merci Guido.“No major systems language has emerged in over a decade, but over that time the computing landscape has changed tremendously. "

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

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