Link Station > Section Généraliste > Discussion Libre >

[TUTORIEL] Programmation Caml




Aller au Forum:
Notez ce sujet :

Page(s) (2): [ 1   2   > ]   Sujet précédent   Sujet suivant
Auteur
Sujet    Tout développer | Tout contracter NOUVEAU SUJET    RÉPONDRE
Réduire ce messageZZakathGuruNiveau 29 · CascadeurRéférenceur Aguerri
Membre depuis
2002
Messages
9866
Plus
Membre n°
7213
Inscription
15 Dec 2002
Localisation
Copenhague
Sujets lancés
426
Ancienneté
97 %
Participation
92 %
Post [TUTORIEL] Programmation CamlAncien message 30-01-2004 21:41
MaJ du 11/02 : tableaux



Je ne suis pas du tout sûr d'être dans la bonne section, donc n'hésitez pas à me déplacer le cas échéant...

Ce post se veut un tutorial d'initiation à la programmation en Caml. Comme j'en suis l'auteur et que je rédige au fur et à mesure, il se peut qu'il y ait des erreurs ou que je ne sois pas clair... N'hésitez pas à me le dire !


Introduction


Tout d'abord, petite présentation de Caml :
Il s'agit d'une version de ML (abbréviation de Meta Language) développée par les petits gars de l'INRIA (à ne pas confondre avec l'INRA ;-)). Par méta-langage, on entend (me semble-t-il, mais cela reste à vérifier) que ce langage a été spécifiquement développé pour que les programmes soient faciles à démontrer (au sens mathématique du terme). Ceci implique une syntaxe claire et structurée (contrairement au C !), mais aussi que Caml est un langage de haut niveau, donc qui ne fait pas se préoccuper la programmeur de questions liées au matériel (comme l'allocation de mémoire en C, par exemple).
Il s'agit également d'un langage fonctionnel, par opposition aux langages dits impératifs (C,...), orientés objet (C++, Java,...) ou logiques (PROLOG,...), bien que Objective Caml (la version de Caml la plus communément usitée, j'y reviendrais) supporte une couche objet. L'exemple-type de langage fonctionnel est Haskell. En bref, dans un langage impératif, on définit une suite d'ordres que l'ordinateur doit effectuer :

Citation

let k = ref 0 in
for i = 1 to 10 do
k:= !k+i
done;


Alors que dans un langage fonctionnel, on définit des fonctions (d'où le nom) qui vont effectuer une action spécifique, puis on appelle les fonctions avec les arguments voulus :

Citation

let sum n =
let k = ref 0 in
for i = 1 to n do
k:= !k+i
done;
!k in

sum 10;;


La différence peut sembler minime. Néanmoins, il s'agit d'une caractéristique importante qui va vite se révéler extrêmement utile, notamment pour écrire du code clair.



Installation

Pour cette section, je supposerai que vous êtes sous windows. De toute manière, l'installation Linux n'est pas plus difficile.

Il existe grosso modo deux distributions de Caml, gérées toutes deux par l'INRIA : Caml Light et Objective Caml. Le premier, comme son nom l'indique, est une version un peu simplifiée. Cela dit, toutes les fonctionnalités nécessaires à la réalisation de programmes avancés sont disponibles. Objective Caml, au contraire, est la version la plus puissante. Le compilateur rivalise même avec C++. Des logiciels comme MLDonkey sont développés en O'Caml. Toutes les librairies sont développées pour O'Caml, alors que Caml Light n'évloue plus. Enfin, O'Caml auorise la création d'éxécutables autonomes, ce qui n'est pas le cas de Caml Light.
Pour toutes ces raisons, j'utiliserai ici O'Caml (NB : si vous connaissez Caml Light, les différences sont très minimes : gestion des opérations sur les structures de données (Liste, Tableau, Chaine...) qui changent de nom et `` (touche 7) des caractères transformés en '' (touche 4)).

Pour installer O'Caml, téléchargez le fichier suivant : https://caml.inria.fr/distrib/ocaml...l2-win-msvc.exe et installez-le dans le répertoire de votre choix (je supposerai que c'est C:\Caml\ dans la suite). Il devrait maintenant y avoir une icône O'Caml sur votre bureau : il s'agit du frontend, ou système interactif. En clair, vous tapez un programme et l'envoyez au système Caml qui se charge de le compiler, l'exécuter et te renvoyer le résultat. Un autre moyen d'utiliser Caml est de compiler puis d'exécuter le programme à partir d'un shell (le prompt MS-DOS sous windows).

Double-cliquez sur Objective Caml : nous voici prêts à commencer.

Mon premier programme
C'est une tradition dans la littérature informatique, le premier programme affiche la chaine de caractère "Hello World". Nous ne dérogerons pas à cette règle. Il faut donc taper les lignes suivantes, en respectant la casse et la ponctuation (NB : un copier/coller ne servira pas à grand chose...) :

Citation

let monPremierProgramme() =
print_string "Hello World";
print_newline();;

monPremierProgramme();;


S'il n'y a pas d'erreur, Caml vous affiche "Hello World" et renvoie la main (c'est le #). Examinons notre code (très simple) :

La première ligne déclare la fonction monPremierProgramme au système. Une déclaration de quelque type que ce soit utilise toujours le mot clé let, le nom de ce qu'on veut déclarer, éventuellement les arguments en cas de déclaration de fonction et enfin le signe =. La déclaration est terminée lorsque l'on rencontre le mot clé in ou ;; (j'y reviendrai).
Comme notre fonction ne doit rien prendre en argument, on le lui précise avec les parenthèses ().
On définit ensuite le corps de la fonction qui consiste en 2 lignes : afficher la chaine (string en anglais) puis effectuer un retour à la ligne. La fonction print_string prend une chaine de caratères en argument et la fonction print_newline ne prend rien : on lui donne donc encore ().
On remarque que deux instructions sont séparées par un ;
La fin d'une séquence d'instructions est déclarée par ;;

Enfin, nous n'avons jusqu'ici fait que définir une fonction. Nous ne demandons encore rien au système Caml. En l'état des choses, nous n'affichons rien. Cette demande est effectuée par l'appel à monPremierProgramme suivi d'un argument vide. L'affichage est alors effectué.



Paramètres et variables

Notre premier programme, même s'il répond à nombre de questions existentielles, n'est pas des plus intéressants car il ne tient absolument pas compte de l'utilisateur. Le rôle de celui-ci se borne à lancer le programme. Or, dans 99,99% des cas, un programme a besoin de demander des instructions à l'utilisateur, du type : combien de fois dois-je effectuer cette opération, quelle chaine de caractères afficher, sur quel tableau effectuer cette opération, etc...
C'est pourquoi nous allons passer à notre fonction des paramètres (ou arguments). On a vu précédemment que la fonction monPremierProgramme ne prenait aucun paramètre en entrée. En réalité, elle prend un argument vide : unit, symbolisé par (). Mais imaginons que nous désirions afficher une chaine quelconque : on doit alors passer en argument la chaine à afficher. Ce qui nous donne :

Citation

let monDeuxièmeProgramme chaine_a_afficher =
print_string chaine_a_afficher;
print_newline();;


On a ici remplacé () par le nom de variable chaine_a_afficher.
Plusieurs remarques :

On peut donner le nom que l'on veut à une variable du moment que cela commence par une lettre et ne contient que des lettres, des chiffres et "_" (touche '8'). Les noms utilisés par Caml, du type "let", "for", "string", etc... sont bien entendus interdits. Dans la pratique, il vaut mieux utiliser des noms plus courts afin de garder des programmes lisibles et de ne pas passer une heure à retaper son nom, mais ne pas non plus exagérer. Si vous utilisez les noms "a", "b", "c", "d", etc sans vous soucier du type de variable et de son utilisation, vous allez très vite être perdus... Les noms du type "str", "text", "opt", "leng"... sont à mon avis les meilleurs compromis.

Contrairement à nombre de langages (au hasard, le C ), vous n'avez pas à déclarer le type de vos variables, Caml le fait tout seul lors de la compilation. Outre un grand confort d'utilisation, cela permet d'éliminer toute erreur de typage (puisque deux instructions donnant des types différents à une variable renverront systématiquement un message d'erreur) et l'usage du polymorphisme (cf plus tard).
Ici, Caml détexte grâce l'instruction "print_string" que la varibale chaine_a_afficher est du type "string".


On peut évidemment passer plusieurs arguments à une fonction, ce qui donnera
Citation
let maFonction x y z t = ...


Dans l'esprit d'un langage fonctionnel, les structures de données ne sont pas mutables. Ce qui veut dire que vous ne pouvez pas les modifier, juste les réassigner grâce à un nouveau "let". Par exemple :

Citation
let i = 10;; (*Assignation de la valeur 10 à la variable i *)

let i = 5;; (* Réassignation de la valeur 5 à i. L'ancienne valeur est oubliée *)

Mais par contre, il n'est pas possible de dire
Citation
let i = i+1;; (*Car la variable est redéfinie à partir du let. Caml ne connait donc pas encore le i de la partie droite *)


Cela dit, les références (équivalents aux pointeurs C) nous permettront ce genre de manipulation : on les déclare en rajoutant ref entre le signe "=" et la valeur initiale. L'accès à leur valeur se fait en ajoutant "!" avant leur nom et leur redéfinition avec le signe ":=".
Citation
let i = ref 10;;
i:= !i+1;;
!i;; (* -> 11 *)



En fonctionnel, chaque fonction prend au moins un argument en entrée et renvoie exactement une valeur en sortie. Cette valeur peut éventuellement être de type unit (vide) comme dans le cas de nos deux fonctions monPremierProgramme et monDeuxièmeProgramme. Cette valeur correspond à ce que renvoie la dernière instruction effectuée.
C'est cette valeur que l'on récupère lorsque l'on appelle la fonction. Voyons un exemple concret : le calcul de la factorielle (selon la définition n! = n * (n-1) * ... * 3 * 2 * 1)

Citation
let factorielle n = (* n est le paramètre : le nombre dont on veut calculer la factorielle *)
let k = ref 1 in (*initialisation de notre référence qui stockera les valeurs intermédiaires *)
for i = 1 to n do (* toutes les instructions contenues entre le do et le done seront répétées en donnant à la variable i toutes les valeurs entre 1 et n *)
k:= !k * i
done;
!k;; (*renvoi de la valeur finale *)


Pour essayer le programme, il suffit de demander à CAML factorielle 10, par exemple, pour obtenir 10! ...


Exercice Ecrire une fonction renvoyant la somme des carrés des entiers de m à n (m et n étant des nombres entiers)...




Une structure élémentaire : le tableau (ou vecteur)

Nous avons vu (brièvement) comment manipuler des variables simples, de types divers, comme les entiers ou les chaines de caractères. Mais il est bien souvent nécessaire de manipuler de très nombreuses variables (plusieurs milliers ou plus). Et on se doute bien qu'on ne va pas s'amuser à déclarer une par une ces variables (d'autant plus que leur nombre peut n'être pas fixé à l'avance !). D'où l'utilisation d'une très pratique structure de données : le tableau.

Quelques faits importants sur le tableau :
- il s'agit d'une structure de données impérative et non fonctionnelle. Quésaco ? En gros, cela veut dire que l'on va modifier les valeurs du tableau à l'intérieur d'une boucle par des opérations de type 'a -> unit, c'est-à-dire qui ne renvoient rien. On ne renvoie pas le tableau obtenu après modification, celui-ci est directement modifié en mémoire : c'est ce qu'on appelle un effet de bord. Dans les langages dits purement fonctionnels, on ne trouve pas du tout d'effets de bords car ceux-ci peuvent poser quelques problèmes au moment du typage (mais ce sont là des points de détails).
- Les tableaux ont une longueur fixe et peuvent contenir un type de données unique. Tous deux sont déclarés au moments de l'initialisation du tableau.
- Par opposition à la structure de liste (que nous verrons plus loin), l'accès à un élément du tableau se fait en un temps constant (en |I]O(1)[/I] pour ceux qui ont fait un peu de maths). Il s'agit du principal avantage d'un tableau.
- Important : Comme pour toutes les structures de données en CAML, le premier élément est l'élément 0ème et le dernier l'élément (n-1)ème si le tableau est de longueur n

Voyons maintenant la syntaxe (en Objective Caml, pour Caml Light, les choses sont un peu différentes). Avant d'appeler une fonction agissant sur un tableau, on précisera à Caml qu'on souhaite utiliser la librairie dédiée aux tableaux en préfixant notre fonction par
Citation
Array.
Le "." est primordial !
Pour initialiser/déclarer un tableau on utilisera la syntaxe :
Citation
let mon_tableau = Array.create longueur element_initial;;

Ceci crée un tableau de longueur l'entier positif longueur et rempli de element_initial. On ne pourra par la suite stocker que des éléments du type de element_initial dans le tableau.

L'accès à l'élément étiqueté par i (où 0 <= i <= longueur-1) se fait par
Citation
mon_tableau.(i)
Là aussi, le point comme les parenthèses sont primordiaux.

La modification d'un élément, elle, est obtenue par
Citation
mon_tableau.(i) <- nouvelle_valeur
Cette fonction est de type int -> 'a -> unit, i.e. on lui donne l'entier correspondant à l'indice et la nouvelle valeur et elle ne renvoie rien !

Pour finir, deux primitives utiles :
Citation
Array.length mon_tableau (* renvoie la longueur du tableau *)
Array.init longueur fonction (* Pas important pour l'instant, mais permet d'initialiser le tableau en appliquant fonction sur les indices du tableau *)


Un exemple de programme utilisant un tableau : le calcul de la factorielle en stockant les valeurs intermédiaires dans un tableau :

Citation
let tab_factorielle n =
let tab = Array.create (n+1) 1 in (* tab.(i) vaudra i! Il nous faut donc (n+1)! cases *)
for i = 1 to n do
tab.(i) <- (tab.(i-1) * i) (* Remplissage du tableau avec la formule de récurrence *)
done;
tab.(n);; (* Renvoi de la valeur finale *)




Exercice : transposer l'exercice précédent en utilisant un tableau.















Annexe : différences entre Caml Light et O'Caml

L'ensemble de ce qu'il faut faire différemment entre Light et Objective est vraiment minime et ne demande quasiment pas de temps d'adaptation.
Voici :

1) les apostrophes autour d'un char, de la combinaison 'Alt Gr' + '7' passent à celles de la touche '4' en accès direct (sur la rangée numérique au dessus de la ligne AZERTYUIOP, bien sûr). Ca a l'air ridicule, mais j'ai passé plus de 2 heures à essayer de débugger un programme correct à cause de ça :'(

2) les instructions de manipulation des structures de données changent. Par exemple, string_length devient String.length : on utilise l'instruction length du module String. De même, List.length, Array.length, etc... Les vect deviennent des Array.
Pour la création de ces structures , on a les instructions create des modules correspondants. Plus puissant (mais inconnu en Light) : les init (cf la doc).
De manière générale, toute opération sur une structure de données utilise un module. Par exemple, rev sur les listes devient List.rev, etc...
Sinon, les primitives de conversion d'un type à un autre (string_of_int, etc...) sont toujours reconnues.

Pour la liste complète des instructions dans les modules, cf : https://caml.inria.fr/ocaml/htmlman...ex_modules.html





Le site officiel de Caml : https://caml.inria.fr/ pour tout savoir.






NB : Ce tuto est destiné à :
1) b.michael.007 qui voulait apprendre un langage
2) moi qui avait envie de faire un truc du genre
3) tous les gens qui veulent bien la lire

__________________
Allez jeter un œil à mon portfolio !

Edité par Zakath le 11-02-2004 à 12:39

Signaler ce message à un modérateur | IP: Logguée

Réduire ce messageKKeySozeModérateurNiveau 25 · Chef opérateurRéférenceur Aguerri
Membre depuis
2002
Messages
6370
Plus
Membre n°
4449
Inscription
15 Sep 2002
Localisation
IDF
Âge
42 ans
Sujets lancés
603
Ancienneté
98 %
Participation
85 %
Ancien message 30-01-2004 22:52
Pour l'instant, ça va j'arrive à suivre
C'est bien en tout cas, vivement la suite

__________________
OXMO : On est plus intelligent à plusieurs que tout seul...mais certains aident moins que d'autres

Signaler ce message à un modérateur | IP: Logguée

Réduire ce messageMMajor TomExpertNiveau 13 · Collectionneur DVDRéférenceur Novice
Membre depuis
2003
Messages
2537
Plus
Membre n°
10924
Inscription
19 Mar 2003
Localisation
ici, et dans d'autres posts également
Sujets lancés
70
Ancienneté
96 %
Participation
68 %
Ancien message 30-01-2004 23:15
Inutile de préciser , que je n'ai absolument rien compris
(inutile également de tenter de m'expliquer pour autant... c'est gentil mais je suis un peu limité dans ce domaine )


Euhh , ca sert à quoi au final ?

@+

__________________



Dépasser les limites c'est bien !
Mais de là à dépasser les bornes... !
Il y a des limites !!!

Signaler ce message à un modérateur | IP: Logguée

Réduire ce messageRRhEcKGuruNiveau 19 · ChroniqueurRéférenceur Novice
Membre depuis
2002
Messages
7657
Plus
Membre n°
5548
Inscription
31 Oct 2002
Localisation
amiens
Âge
42 ans
Sujets lancés
66
Ancienneté
98 %
Participation
88 %
Re: [TUTORIEL] Programmation CamlAncien message 31-01-2004 10:22
Message écrit par Zakath, le 30-01-2004 à 21:41
NB : Ce tuto est destiné à :
1) b.michael.007 qui voulait apprendre un langage
2) moi qui avait envie de faire un truc du genre
3) tous les gens qui veulent bien la lire



moi j'en voudrais bien si tu mets les equivalents en O caml si c'est different pour que je m'habitue


merci

__________________
mess with the best, die like the rest


<<~~=!!!RhEcK!!!=~~>>

Signaler ce message à un modérateur | IP: Logguée

Réduire ce messageBbobounetConfirméNiveau 7 · CinéphageRéférenceur Novice
Membre depuis
2002
Messages
1385
Plus
Membre n°
699
Inscription
18 Mar 2002
Localisation
Paris
Âge
44 ans
Sujets lancés
18
Ancienneté
100 %
Participation
57 %
Ancien message 31-01-2004 17:29
Très bonne idée .
Merci Zakath, ton poste va me servir pour mon 2ème semestre.

Signaler ce message à un modérateur | IP: Logguée

Réduire ce messageGgortoggConfirméNiveau 9 · Abonné Canal+Référenceur Appliqué
Membre depuis
2002
Messages
1321
Plus
Membre n°
6145
Inscription
16 Nov 2002
Localisation
Freux ou Bominable, ça dépend des jours
Âge
45 ans
Sujets lancés
38
Ancienneté
98 %
Participation
56 %
Ancien message 01-02-2004 10:34
pouah, ça sent le taupin ici
Sinon caml c'est très marrant (ce dont je me souviens), et l'avantage, c'est que c'est un langage qui sait "quasiment" rien faire, donc faut tout coder, la vraie fête quoi.

__________________
"Si tu peux te quoter toi même, t'es trop fort" Gortogg

Signaler ce message à un modérateur | IP: Logguée

Réduire ce messageSServefConfirméNiveau 9 · Abonné Canal+Référenceur Novice
Membre depuis
2003
Messages
1258
Plus
Membre n°
12751
Inscription
27 Apr 2003
Localisation
Far far away...
Âge
46 ans
Sujets lancés
54
Ancienneté
96 %
Participation
55 %
Ancien message 01-02-2004 11:04
AAAah, Caml...ma première feuille blanche !

__________________
My trumpet is rich.

Signaler ce message à un modérateur | IP: Logguée

Réduire ce messageSSolacinGuruNiveau 11 · CinéphileRéférenceur Novice
Membre depuis
2003
Messages
8254
Plus
Membre n°
11117
Inscription
23 Mar 2003
Localisation
974
Âge
52 ans
Sujets lancés
28
Ancienneté
96 %
Participation
89 %
Ancien message 02-02-2004 07:17
Ben moi aussi j'ai tout bien compris !!!!!!!!!!!!!
Encore encore

__________________

Signaler ce message à un modérateur | IP: Logguée

Réduire ce messageRRhEcKGuruNiveau 19 · ChroniqueurRéférenceur Novice
Membre depuis
2002
Messages
7657
Plus
Membre n°
5548
Inscription
31 Oct 2002
Localisation
amiens
Âge
42 ans
Sujets lancés
66
Ancienneté
98 %
Participation
88 %
Ancien message 02-02-2004 19:18
Message écrit par gortogg, le 01-02-2004 à 10:34
pouah, ça sent le taupin ici
Sinon caml c'est très marrant (ce dont je me souviens), et l'avantage, c'est que c'est un langage qui sait "quasiment" rien faire, donc faut tout coder, la vraie fête quoi.



dans le quasiment il y a la structure de liste quand meme et c'est pas rien


s'amuser a allouer de la memoire et gerer les listes chainees en C c'est pas genial quand meme (meme si ca permet plus de souplesse)

__________________
mess with the best, die like the rest


<<~~=!!!RhEcK!!!=~~>>

Signaler ce message à un modérateur | IP: Logguée

Réduire ce messageOOyoooConfirméNiveau 5 · Fan de VHS
Membre depuis
2002
Messages
719
Plus
Membre n°
1103
Inscription
13 Apr 2002
Localisation
Rennes
Âge
46 ans
Sujets lancés
5
Ancienneté
100 %
Participation
45 %
Ancien message 02-02-2004 19:24
Sympa comme tuto
Ca tombe bien je refais du CAML cette année

Signaler ce message à un modérateur | IP: Logguée

Réduire ce messageZzevinceMaitreNiveau 11 · CinéphileRéférenceur Novice
Membre depuis
2003
Messages
3439
Plus
Membre n°
10414
Inscription
08 Mar 2003
Âge
54 ans
Sujets lancés
23
Ancienneté
96 %
Participation
73 %
Ancien message 03-02-2004 12:47
Wouyah... et dans la pratique.. c'est un langage qui est utilisé dans quels domaines ?
Moi j'ai un peu appris sur le tas, et CAML, ca a l'air plutot .. hermetique, a premiere vue.. bien plus que XSLT ou PHP

Signaler ce message à un modérateur | IP: Logguée

Réduire ce messageZZakathGuruNiveau 29 · CascadeurRéférenceur Aguerri
Membre depuis
2002
Messages
9866
Plus
Membre n°
7213
Inscription
15 Dec 2002
Localisation
Copenhague
Sujets lancés
426
Ancienneté
97 %
Participation
92 %
Ancien message 03-02-2004 21:27
J'ai un peu (beaucoup) une semaine crevante et mon PC est squatté par ma soeur, donc je ne pense pas reposter avant dimanche prochain...

Et pour zevince, je toruve CAML mille fois plus clair et moins abscons que C (voire Java). Très honnêtement, ca s'apprend vite et ca n'est pas hermétique pour deux sous (NB : ceci est toujours un avis personnel).

@ Rheck : je te poste ça dimanche, voire avant. Et pour Centrale 2001, je n'ai rien rédigé...

__________________
Allez jeter un œil à mon portfolio !

Signaler ce message à un modérateur | IP: Logguée

Réduire ce messageGgortoggConfirméNiveau 9 · Abonné Canal+Référenceur Appliqué
Membre depuis
2002
Messages
1321
Plus
Membre n°
6145
Inscription
16 Nov 2002
Localisation
Freux ou Bominable, ça dépend des jours
Âge
45 ans
Sujets lancés
38
Ancienneté
98 %
Participation
56 %
Ancien message 03-02-2004 23:05
@zevince: dans la pratique Caml sert pas mal dans le domaine des transports (ex: ligne 14 du métro parisien, nom de code "Meteor", tout y est programmé en Caml).

A part ça, rien d'autre à ma connaissance.

__________________
"Si tu peux te quoter toi même, t'es trop fort" Gortogg

Signaler ce message à un modérateur | IP: Logguée

Réduire ce messageRRiccoConfirméNiveau 7 · CinéphageRéférenceur Novice
Membre depuis
2002
Messages
842
Plus
Membre n°
629
Inscription
13 Mar 2002
Localisation
Dans le 9 4
Âge
46 ans
Sujets lancés
39
Ancienneté
100 %
Participation
48 %
Ancien message 03-02-2004 23:16
Lol ... je dis pas ça pour toi gotogg, mais a chaque fois qu'on a un cours de spec, reseau de pétri ou autre ils trouvent toujours le moyen de nous glisser météor )

Faudrait savoir !

__________________
"Hi ! I am a signature virus ! Put me in your signature to help me spread myself around this forum !"

Signaler ce message à un modérateur | IP: Logguée

Réduire ce messageSSolacinGuruNiveau 11 · CinéphileRéférenceur Novice
Membre depuis
2003
Messages
8254
Plus
Membre n°
11117
Inscription
23 Mar 2003
Localisation
974
Âge
52 ans
Sujets lancés
28
Ancienneté
96 %
Participation
89 %
Ancien message 04-02-2004 04:53
HAHAHAHA ........ pour une fois qu'ils ont une référence valide et concrète à donner, ils s'en servent !!!!!!

__________________

Signaler ce message à un modérateur | IP: Logguée

Il est actuellement 18:17 (GMT) NOUVEAU SUJET    RÉPONDRE   
Page(s) (2): [ 1   2   > ]  Sujet précédent   Sujet suivant
Link Station > Section Généraliste > Discussion Libre > [TUTORIEL] Programmation Caml

Aller au Forum:
Notez ce sujet :


Réponse rapide
Afficher une version imprimable | Chercher dans ce sujet | Envoyer cette page par email | S'inscrire à ce sujet | Télécharger ce sujet
Règles du forum :
Créer de nouveaux sujets
Répondre aux messages
Attacher des fichiers
Editer vos messages
: not autorisé
: not autorisé
: not autorisé
: not autorisé
Le Code HTML est OFF
Le BBCode est ON
Les Smileys sont ONs
Le code [IMG] est ON
Page générée en 0.056822 secondes en exécutant 50 requêtes SQL.
Apache - Compression GZIP : Activée.