summaryrefslogtreecommitdiffhomepage
path: root/fr-fr
diff options
context:
space:
mode:
Diffstat (limited to 'fr-fr')
-rw-r--r--fr-fr/clojure-fr.html.markdown398
-rw-r--r--fr-fr/coffeescript-fr.html.markdown58
-rw-r--r--fr-fr/csharp-fr.html.markdown812
-rw-r--r--fr-fr/haskell.html.markdown431
-rw-r--r--fr-fr/lua-fr.html.markdown449
-rw-r--r--fr-fr/objective-c-fr.html.markdown528
-rw-r--r--fr-fr/python-fr.html.markdown489
-rw-r--r--fr-fr/racket-fr.html.markdown628
-rw-r--r--fr-fr/ruby-fr.html.markdown411
9 files changed, 4204 insertions, 0 deletions
diff --git a/fr-fr/clojure-fr.html.markdown b/fr-fr/clojure-fr.html.markdown
new file mode 100644
index 00000000..d3c5a67b
--- /dev/null
+++ b/fr-fr/clojure-fr.html.markdown
@@ -0,0 +1,398 @@
+---
+language: clojure
+filename: learnclojure-fr.clj
+contributors:
+ - ["Adam Bard", "http://adambard.com/"]
+translators:
+ - ["Bastien Guerry", "https://github.com/bzg"]
+lang: fr-fr
+---
+
+Clojure est un langage de la famille des Lisp développé pour la machine
+virtuelle Java. Ce langage insiste beaucoup plus sur la [programmation
+fonctionnelle](https://fr.wikipedia.org/wiki/Programmation_fonctionnelle) pure
+que Common Lisp, mais comprend plusieurs outils de gestion de la mémoire
+transactionnelle
+[STM](https://en.wikipedia.org/wiki/Software_transactional_memory) pour gérer
+les changements d'états si besoin.
+
+Cette combinaison permet de gérer le parallélisme très simplement, et
+souvent de façon automatique.
+
+(Vous avez besoin de Clojure 1.2 ou plus récent pour ce tutoriel.)
+
+```clojure
+; Les commentaires commencent avec un point-virgule.
+
+; Clojure est composé de « formes », qui sont simplement des listes
+; d'expressions entre parenthèses, séparées par une ou des espaces.
+;
+; L'interpréteur Clojure suppose que le premier élément est une fonction
+; ou une macro, et que le reste contient des arguments.
+
+; Le premier appel dans un fichier doit être ns, pour définir
+; l'espace de nom
+(ns learnclojure)
+
+; D'autres d'exemples basiques:
+
+; str va créer une chaîne de caractères à partir de tous ses arguments
+(str "Hello" " " "World") ; => "Hello World"
+
+; Les opérations mathématiques sont simples
+(+ 1 1) ; => 2
+(- 2 1) ; => 1
+(* 1 2) ; => 2
+(/ 2 1) ; => 2
+
+; L'égalité est =
+(= 1 1) ; => true
+(= 2 1) ; => false
+
+; Vous avez aussi besoin de not pour la négation logique
+(not true) ; => false
+
+; Les formes imbriquées fonctionnent comme on s'y attend
+(+ 1 (- 3 2)) ; = 1 + (3 - 2) => 2
+
+; Types
+;;;;;;;;;;;;;
+
+; Clojure utilise les types d'objets Java pour les booléens, les chaînes de
+; caractères et les nombres.
+; Utilisez `class` pour inspecter les types.
+(class 1) ; Les nombres entiers littéraux sont java.lang.Long par défaut
+(class 1.); Les flottants littéraux sont java.lang.Double
+(class ""); Les chaînes sont toujours entourées de guillemets doubles, et sont java.lang.String
+(class false) ; Les booléens sont java.lang.Boolean
+(class nil); La valeur "null" est appelée nil
+
+; Si vous voulez créer une liste littérale de données, utilisez ' pour en
+; empêcher son évaluation
+'(+ 1 2) ; => (+ 1 2)
+; (qui est un raccourci pour (quote (+ 1 2)))
+
+; Vous pouvez évaluer une liste "quotée":
+(eval '(+ 1 2)) ; => 3
+
+; Collections & séquences
+;;;;;;;;;;;;;;;;;;;;;;;;;
+
+; Les listes sont des structures de données en listes chaînées, alors que les
+; vecteurs reposent sur des tableaux.
+; Les vecteurs et les listes sont des classes Java aussi !
+(class [1 2 3]); => clojure.lang.PersistentVector
+(class '(1 2 3)); => clojure.lang.PersistentList
+
+; Une liste serait écrite comme (1 2 3), mais nous devons la quoter
+; pour empêcher l'interpréteur de penser que c'est une fonction.
+; Et (list 1 2 3) est la même chose que '(1 2 3)
+
+; Les "Collections" sont juste des groupes de données
+; Les listes et les vecteurs sont tous deux des collections:
+(coll? '(1 2 3)) ; => true
+(coll? [1 2 3]) ; => true
+
+; Les "séquences" (seqs) sont des abstractions à partir de listes de données.
+; Seules les listes sont elles-mêmes des séquences.
+(seq? '(1 2 3)) ; => true
+(seq? [1 2 3]) ; => false
+
+; Une séquence n'a besoin de fournir une entrée que lorsqu'on y accède.
+; Donc, les séquences peuvent être "lazy" -- et définir une série infinie:
+(range 4) ; => (0 1 2 3)
+(range) ; => (0 1 2 3 4 ...) (une série infinie)
+(take 4 (range)) ; (0 1 2 3)
+
+; Utilisez cons pour ajouter un item au début d'une liste ou d'un vecteur
+(cons 4 [1 2 3]) ; => (4 1 2 3)
+(cons 4 '(1 2 3)) ; => (4 1 2 3)
+
+; Conj ajoutera un item à une collection de la manière la plus efficace
+; Pour les listes, conj ajoute l'item au début; pour les vecteurs, à la fin.
+(conj [1 2 3] 4) ; => [1 2 3 4]
+(conj '(1 2 3) 4) ; => (4 1 2 3)
+
+; Utilisez concat pour ajouter des listes ou vecteurs:
+(concat [1 2] '(3 4)) ; => (1 2 3 4)
+
+; Utilisez filter, map pour interagir avec des collections
+(map inc [1 2 3]) ; => (2 3 4)
+(filter even? [1 2 3]) ; => (2)
+
+; Utilisez reduce pour les réduire
+(reduce + [1 2 3 4])
+; = (+ (+ (+ 1 2) 3) 4)
+; => 10
+
+; Reduce peut aussi prendre un argument pour la valeur initiale
+(reduce conj [] '(3 2 1))
+; = (conj (conj (conj [] 3) 2) 1)
+; => [3 2 1]
+
+; Fonctions
+;;;;;;;;;;;;;;;;;;;;;
+
+; Utilisez fn pour créer de nouvelles fonctions.
+; Une fonction renvoie toujours sa dernière expression.
+(fn [] "Hello World") ; => fn
+
+; (Vous devez ajouter des parenthèses pour l'appeler)
+((fn [] "Hello World")) ; => "Hello World"
+
+; Vous pouvez créer une variable en utilisant def
+(def x 1)
+x ; => 1
+
+; Assignez une fonction à une variable
+(def hello-world (fn [] "Hello World"))
+(hello-world) ; => "Hello World"
+
+; Vous pouvez raccourcir le procédé en utilisant defn
+(defn hello-world [] "Hello World")
+
+; [] contient la liste des arguments de la fonction
+(defn hello [name]
+ (str "Hello " name))
+(hello "Steve") ; => "Hello Steve"
+
+; Vous pouvez aussi utiliser ce raccourci pour créer des fonctions
+(def hello2 #(str "Hello " %1))
+(hello2 "Fanny") ; => "Hello Fanny"
+
+; Vous pouvez avoir des fonctions multi-variadiques
+(defn hello3
+ ([] "Hello World")
+ ([name] (str "Hello " name)))
+(hello3 "Jake") ; => "Hello Jake"
+(hello3) ; => "Hello World"
+
+; Les fonctions peuvent inclure des arguments supplémentaires dans une séquence
+(defn count-args [& args]
+ (str "You passed " (count args) " args: " args))
+(count-args 1 2 3) ; => "Vous avez passé 3 args: (1 2 3)"
+
+; Vous pouvez combiner les arguments normaux et supplémentaires
+(defn hello-count [name & args]
+ (str "Hello " name ", vous avez passé " (count args) " args supplémentaires"))
+(hello-count "Finn" 1 2 3)
+; => "Hello Finn, vous avez passé 3 args supplémentaires"
+
+
+; Maps
+;;;;;;;;;;;;;;;
+
+; Les hashmaps et les arraymaps partagent une interface. Les hashmaps
+; sont interrogés plus rapidement mais ne retiennent pas l'ordre des clefs.
+(class {:a 1 :b 2 :c 3}) ; => clojure.lang.PersistentArrayMap
+(class (hash-map :a 1 :b 2 :c 3)) ; => clojure.lang.PersistentHashMap
+
+; Les array maps deviennent automatiquement des hashmaps pour la
+; plupart des opérations si elles deviennent assez larges, donc vous
+; n'avez pas à vous en faire.
+
+; Tous les types "hashables" sont acceptés comme clefs, mais en
+; général on utilise des mots-clefs ("keywords")
+; Les mots-clefs sont comme les chaînes de caractères mais en plus efficaces
+(class :a) ; => clojure.lang.Keyword
+
+(def stringmap {"a" 1, "b" 2, "c" 3})
+stringmap ; => {"a" 1, "b" 2, "c" 3}
+
+(def keymap {:a 1, :b 2, :c 3})
+keymap ; => {:a 1, :c 3, :b 2}
+
+; Au passage, les virgules sont toujours traitées comme des espaces et
+; ne font rien.
+
+; Sélectionnez une valeur dans une map en l'appelant comme fonction
+(stringmap "a") ; => 1
+(keymap :a) ; => 1
+
+; Les mots-clefs peuvent aussi être utilisés pour sélectionner leur
+; valeur dans une map !
+(:b keymap) ; => 2
+
+; N'essayez pas ça avec les chaînes de caractères
+;("a" stringmap)
+; => Exception: java.lang.String cannot be cast to clojure.lang.IFn
+
+; Sélectionner une clef absente renvoie nil
+(stringmap "d") ; => nil
+
+; Use assoc to add new keys to hash-maps
+(def newkeymap (assoc keymap :d 4))
+newkeymap ; => {:a 1, :b 2, :c 3, :d 4}
+
+; Mais souvenez-vous, les types en Clojure sont immuables !
+keymap ; => {:a 1, :b 2, :c 3}
+
+; Utilisez dissoc pour retirer des clefs
+(dissoc keymap :a :b) ; => {:c 3}
+
+; Ensembles
+;;;;;;;;;;;;;;;
+
+(class #{1 2 3}) ; => clojure.lang.PersistentHashSet
+(set [1 2 3 1 2 3 3 2 1 3 2 1]) ; => #{1 2 3}
+
+; Ajoutez un élément avec conj
+(conj #{1 2 3} 4) ; => #{1 2 3 4}
+
+; Retirez-en un avec disj
+(disj #{1 2 3} 1) ; => #{2 3}
+
+; Testez la présence en utilisant l'ensemble comme une fonction
+(#{1 2 3} 1) ; => 1
+(#{1 2 3} 4) ; => nil
+
+; Il y a encore d'autres fonctions dans l'espace de nom clojure.sets.
+
+; Formes utiles
+;;;;;;;;;;;;;;;
+
+; Les constructions logiques en Clojure sont juste des macros, et
+ressemblent à toutes les autres formes:
+(if false "a" "b") ; => "b"
+(if false "a") ; => nil
+
+; Utilisez let pour créer des assignations temporaires
+(let [a 1 b 2]
+ (> a b)) ; => false
+
+; Groupez les énoncés ensemble avec do
+(do
+ (print "Hello")
+ "World") ; => "World" (prints "Hello")
+
+; Les fonctions ont un do implicit
+(defn print-and-say-hello [name]
+ (print "Saying hello to " name)
+ (str "Hello " name))
+(print-and-say-hello "Jeff") ;=> "Hello Jeff" (prints "Saying hello to Jeff")
+
+; De même pour let
+(let [name "Urkel"]
+ (print "Saying hello to " name)
+ (str "Hello " name)) ; => "Hello Urkel" (prints "Saying hello to Urkel")
+
+; Modules
+;;;;;;;;;;;;;;;
+
+; Utilisez "use" pour obtenir toutes les fonctions d'un module
+(use 'clojure.set)
+
+; Maintenant nous pouvons utiliser les opération de set
+(intersection #{1 2 3} #{2 3 4}) ; => #{2 3}
+(difference #{1 2 3} #{2 3 4}) ; => #{1}
+
+; Vous pouvez aussi choisir un sous-ensemble de fonctions à importer
+(use '[clojure.set :only [intersection]])
+
+; Utilisez require pour importer un module
+(require 'clojure.string)
+
+; Utilisez / pour appeler les fonctions d'un module
+; Ici, le module est clojure.string et la fonction est blank?
+(clojure.string/blank? "") ; => true
+
+; Vous pouvez associer un nom plus court au module au moment de l'importer
+(require '[clojure.string :as str])
+(str/replace "This is a test." #"[a-o]" str/upper-case) ; => "THIs Is A tEst."
+; (#"" dénote une expression régulière)
+
+; Vous pouvez utiliser require (et use, mais ne le faites pas) en
+; appelant :require depuis un espace de noms.
+; Dans ce cas-là, vous n'avez pas besoin de "quoter" vos modules:
+(ns test
+ (:require
+ [clojure.string :as str]
+ [clojure.set :as set]))
+
+; Java
+;;;;;;;;;;;;;;;;;
+
+; Java a une librairie standard énorme, donc vous voudrez apprendre à
+; vous familiariser avec.
+
+; Utilisez import pour charger un module java
+(import java.util.Date)
+
+; Vous pouvez importer depuis un ns aussi.
+(ns test
+ (:import java.util.Date
+ java.util.Calendar))
+
+; Utilisez les noms de classes avec "." à la fin pour créer une instance
+(Date.) ; <un objet date>
+
+; Utilisez . pour invoquer des méthodes. Ou utilisez le raccourci ".method"
+(. (Date.) getTime) ; <un timestamp>
+(.getTime (Date.)) ; exactement la même chose
+
+; Utilisez / pour appeler des méthodes statiques
+(System/currentTimeMillis) ; <un timestamp> (system est toujours présent)
+
+; Utilisez doto to rendre plus tolérable l'interaction avec des
+; classes (mutables)
+(import java.util.Calendar)
+(doto (Calendar/getInstance)
+ (.set 2000 1 1 0 0 0)
+ .getTime) ; => Une classe Date. définie comme 2000-01-01 00:00:00
+
+; STM
+;;;;;;;;;;;;;;;;;
+
+; La mémoire logiciel transactionnelle ("Software Transactional Memory")
+; est le mécanisme que Clojure utilise pour gérer les états persistents.
+; Il y a plusieurs formes en Clojure qui utilisent cela.
+
+; L'atome est la plus simple. Passez-lui une valeur initiale
+(def my-atom (atom {}))
+
+; Mettez à jour un atome avec swap!.
+; swap! prend une fonction en argument et l'appelle avec la valeur
+; actuelle de l'atome comme premier argument, et les autres arguments
+; comme second argument.
+(swap! my-atom assoc :a 1) ; Définit my-atom comme le résultat de (assoc {} :a 1)
+(swap! my-atom assoc :b 2) ; Définit my-atom comme le résultat de (assoc {:a 1} :b 2)
+
+; Use '@' to dereference the atom and get the value
+my-atom ;=> Atom<#...> (Renvoie l'objet Atom)
+@my-atom ; => {:a 1 :b 2}
+
+; Voici un simple compteur utilisant un atome
+(def counter (atom 0))
+(defn inc-counter []
+ (swap! counter inc))
+
+(inc-counter)
+(inc-counter)
+(inc-counter)
+(inc-counter)
+(inc-counter)
+
+@counter ; => 5
+
+; Les autres formes STM sont les refs et les agents.
+; Refs: http://clojure.org/refs
+; Agents: http://clojure.org/agents
+```
+
+### Lectures complémentaires
+
+C'est loin d'être exhaustif, mais assez pour vous permettre de continuer.
+
+Clojure.org propose de nombreux articles:
+[http://clojure.org/](http://clojure.org/)
+
+Clojuredocs.org a de la documentation avec des exemples pour la
+plupart des fonctions principales :
+[http://clojuredocs.org/quickref/Clojure%20Core](http://clojuredocs.org/quickref/Clojure%20Core)
+
+4Clojure est une super manière d'augmenter vos compétences en Clojure et
+en programmation fonctionnelle :
+[http://www.4clojure.com/](http://www.4clojure.com/)
+
+Clojure-doc.org a pas mal d'article pour débuter :
+[http://clojure-doc.org/](http://clojure-doc.org/)
diff --git a/fr-fr/coffeescript-fr.html.markdown b/fr-fr/coffeescript-fr.html.markdown
new file mode 100644
index 00000000..c66b7be0
--- /dev/null
+++ b/fr-fr/coffeescript-fr.html.markdown
@@ -0,0 +1,58 @@
+---
+language: coffeescript
+contributors:
+ - ["Tenor Biel", "http://github.com/L8D"]
+translators:
+ - ["Geoffrey Roguelon", "https://github.com/GRoguelon"]
+lang: fr-fr
+filename: coffeescript-fr.coffee
+---
+
+``` coffeescript
+# CoffeeScript est un langage préprocesseur, il permet de générer du Javascript.
+# Il suit les tendances de certains langages récents.
+# Par exemple, les commentaires se définissent comme en Ruby ou en Python.
+
+###
+Ceci est un bloc de commentaires
+il est converti directement avec '/ *' et '* /'
+pour correspondre aux commentaires Javascript
+
+Vous devez comprendre la syntaxe du langage JavaScript pour continuer.
+###
+
+# Affectation :
+number = 42 #=> var number = 42;
+opposite = true #=> var opposite = true;
+
+# Structures de contrôle :
+number = -42 if opposite #=> if(opposite) { number = -42; }
+
+# Fonctions :
+square = (x) -> x * x #=> var square = function(x) { return x * x; }
+
+# Intervals :
+list = [1..5] #=> var list = [1, 2, 3, 4, 5];
+
+# Objets :
+math =
+ root: Math.sqrt
+ square: square
+ cube: (x) -> x * square x
+#=> var math = {
+# "root": Math.sqrt,
+# "square": square,
+# "cube": function(x) { return x * square(x); }
+#}
+
+# Liste d'arguments variables :
+race = (winner, runners...) ->
+ print winner, runners
+
+# Existance :
+alert "I knew it!" if elvis?
+#=> if(typeof elvis !== "undefined" && elvis !== null) { alert("I knew it!"); }
+
+# Lecture d'un tableau :
+cubes = (math.cube num for num in list) #=> ...
+```
diff --git a/fr-fr/csharp-fr.html.markdown b/fr-fr/csharp-fr.html.markdown
new file mode 100644
index 00000000..c1641716
--- /dev/null
+++ b/fr-fr/csharp-fr.html.markdown
@@ -0,0 +1,812 @@
+---
+language: c#
+contributors:
+ - ["Irfan Charania", "https://github.com/irfancharania"]
+ - ["Max Yankov", "https://github.com/golergka"]
+ - ["Melvyn Laïly", "http://x2a.yt"]
+ - ["Shaun McCarthy", "http://www.shaunmccarthy.com"]
+translators:
+ - ["Olivier Hoarau", "https://github.com/Olwaro"]
+filename: LearnCSharp.cs
+lang: fr-fr
+---
+
+C# est un langage de programmation orienté objet à typage fort qui permet aux développeurs de créer une grande variété d'applications fiables et robustes s'appuyant sur le framework .NET.
+
+[Plus d'infos](http://msdn.microsoft.com/fr-fr/library/67ef8sbd.aspx)
+
+```c#
+// Les commentaires sur une seule ligne commencent par //
+/*
+Les
+commentaires
+multi-lignes
+ressemblent
+ceci
+*/
+/// <summary>
+/// Ceci est un commentaire de documentation XML
+/// </summary>
+
+// Importez des namespaces avec l'instruction 'using'
+using System;
+using System.Collections.Generic;
+using System.Data.Entity;
+using System.Dynamic;
+using System.Linq;
+using System.Linq.Expressions;
+using System.Net;
+using System.Threading.Tasks;
+
+// Définit la portée du code pour une meilleure organisation
+namespace Learning
+{
+ // Chaque fichier .cs devrait au moins contenir une classe avec le même nom
+ // que celui du fichier. Ce n'est pas une obligation mais c'est mieux !
+ public class LearnCSharp
+ {
+ // LES BASES - si vous avez déjà de l'expérience en Java ou C++
+ // passez directement à la partie FONCTIONNALITÉS INTERÉSSANTES
+ public static void Syntax()
+ {
+ // Utilisez Console.WriteLine pour écrire sur la sortie
+ Console.WriteLine("Hello World");
+ Console.WriteLine(
+ "Entier: " + 10 +
+ " Double: " + 3.14 +
+ " Booleen: " + true);
+
+ // Pour omettre le retour à la ligne : Console.Write
+ Console.Write("Hello ");
+ Console.Write("World");
+
+ ///////////////////////////////////////////////////
+ // Types et Variables
+ // Déclarez une variable avec la syntaxe <type> <nom>
+ ///////////////////////////////////////////////////
+
+ // Sbyte - Entier signé sur 8 bits
+ // (-128 <= sbyte <= 127)
+ sbyte fooSbyte = 100;
+
+ // Byte - Entier non-signé sur 8 bits
+ // (0 <= byte <= 255)
+ byte fooByte = 100;
+
+ // Short - Entier sur 16 bits
+ // Signé - (-32,768 <= short <= 32,767)
+ // Non-signé - (0 <= ushort <= 65,535)
+ short fooShort = 10000;
+ ushort fooUshort = 10000;
+
+ // Int - Entier sur 32 bits
+ int fooInt = 1; // (-2,147,483,648 <= int <= 2,147,483,647)
+ uint fooUint = 1; // (0 <= uint <= 4,294,967,295)
+
+ // Long - Entier sur 64 bits
+ long fooLong = 100000L; // (-9,223,372,036,854,775,808 <= long <= 9,223,372,036,854,775,807)
+ ulong fooUlong = 100000L; // (0 <= ulong <= 18,446,744,073,709,551,615)
+ // Par défaut le type d'un littéral entier est int ou uint
+ // on ajoute 'L' pour spécifier la création d'un long
+
+ // Double - Réel sur 64 bits en virgule flottante (norme IEEE 754)
+ double fooDouble = 123.4; // Precision : 15-16 chiffres
+
+ // Float - Réel sur 32 bits en virgule flottante (norme IEEE 754)
+ float fooFloat = 234.5f; // Precision : 7 chiffres
+ // Par défaut le type d'un littéral réel est double
+ // on ajoute 'f' pour spécifier la création d'un float
+
+ // Decimal - Type de donnée numérique sur 128 bits, fournit une plus
+ // grande précision et une plage de valeurs réduite.
+ // Approprié aux calculs financiers et monétaires
+ decimal fooDecimal = 150.3m;
+
+ // Booléen - vrai / faux
+ bool fooBoolean = true; // ou false
+
+ // Char - Un unique caractère Unicode sur 16 bits
+ char fooChar = 'A';
+
+ // String -- contrairement aux types précédents qui sont des types valeurs,
+ // string est un type référence. Il peut donc avoir la valeur null
+ string fooString = "\"échappement\" de guillemets et ajout de \n (nouvelle ligne) et de \t (tabulation)";
+ Console.WriteLine(fooString);
+
+ // Il est possible d'accéder à chaque caractère d'une chaîne de caractères via son index
+ char charFromString = fooString[1]; // 'é'
+ // une chaîne de caractères est immuable : impossible de faire fooString[1] = 'X';
+
+ // Comparaison de chaînes de caractères avec la culture courrante en ignorant la casse
+ string.Compare(fooString, "x", StringComparison.CurrentCultureIgnoreCase);
+
+ // Formatage
+ string fooFs = string.Format("Check Check, {0} {1}, {0} {1:0.0}", 1, 2);
+
+ // Dates et formatage
+ DateTime fooDate = DateTime.Now;
+ Console.WriteLine(fooDate.ToString("hh:mm, dd MMM yyyy"));
+
+ // Il est possible d'étaler une chaîne de caractères sur plusieurs lignes avec le symbole @.
+ // Pour échapper " utilisez ""
+ string bazString = @"Voici quelques trucs
+sur une nouvelle ligne! ""Wow!"", quel style";
+
+ // Utilisez const ou read-only pour rendre une variable immuable.
+ // Les valeurs constantes sont calculées au moment de la compilation
+ const int HOURS_I_WORK_PER_WEEK = 9001;
+
+ ///////////////////////////////////////////////////
+ // Structures de données
+ ///////////////////////////////////////////////////
+
+ // Tableaux - indexé à partir de zéro
+ // La taille d'un tableau doit être décidée à la déclaration
+ // La syntaxe pour déclarer un tableau est la suivante :
+ // <type>[] <nom> = new <type>[<taille>]
+ int[] intArray = new int[10];
+
+ // Une autre méthode de déclaration et d'initialisation
+ int[] y = { 9000, 1000, 1337 };
+
+ // Indexer un tableau - Accéder à un élément
+ Console.WriteLine("intArray à 0: " + intArray[0]);
+ // Les tableaux sont muables.
+ intArray[1] = 1;
+
+ // Listes
+ // Elles sont plus souvent utilisées que les tableaux car plus souples
+ // La syntaxe pour déclarer une liste est la suivante :
+ // List<type> <nom> = new List<type>();
+ List<int> intList = new List<int>();
+ List<string> stringList = new List<string>();
+ List<int> z = new List<int> { 9000, 1000, 1337 }; // intialisation
+ // Les <> indiquent un type générique
+ // Pus d'info dans la partie FONCTIONNALITÉS INTERÉSSANTES
+
+ // Les éléments d'une liste ne sont pas null par défaut
+ // Il faut ajouter une valeur avant d'y accéder par index
+ intList.Add(1);
+ Console.WriteLine("intList à 0: " + intList[0]);
+
+ // Autres structures de données à étudier :
+ // Stack/Queue (Pile/File)
+ // Dictionary (une implémentation de hash map)
+ // HashSet (représente un ensemble)
+ // Collections en lecture seule
+ // Tuple (.Net 4+)
+
+ ///////////////////////////////////////
+ // Opérateurs
+ ///////////////////////////////////////
+ Console.WriteLine("\n->Opérateurs");
+
+ int i1 = 1, i2 = 2; // Raccourci pour des déclarations multiples
+
+ // Arithmétique classique
+ Console.WriteLine(i1 + i2 - i1 * 3 / 7); // => 3
+
+ // Modulo
+ Console.WriteLine("11%3 = " + (11 % 3)); // => 2
+
+ // Opérateurs de comparaison
+ Console.WriteLine("3 == 2? " + (3 == 2)); // => False
+ Console.WriteLine("3 != 2? " + (3 != 2)); // => True
+ Console.WriteLine("3 > 2? " + (3 > 2)); // => True
+ Console.WriteLine("3 < 2? " + (3 < 2)); // => False
+ Console.WriteLine("2 <= 2? " + (2 <= 2)); // => True
+ Console.WriteLine("2 >= 2? " + (2 >= 2)); // => True
+
+ // Opérateurs bit à bit !
+ /*
+ ~ Compément unaire
+ << Décalage à gauche
+ >> Décalage à droite
+ & ET logique
+ ^ OU exclusif
+ | OU inclusif
+ */
+
+ // Incrémentations
+ int i = 0;
+ Console.WriteLine("\n->Inc/Dec-rementation");
+ Console.WriteLine(i++); //i = 1. Post-Incrémentation
+ Console.WriteLine(++i); //i = 2. Pre-Incrémentation
+ Console.WriteLine(i--); //i = 1. Post-Decrémentation
+ Console.WriteLine(--i); //i = 0. Pre-Decrémentation
+
+ ///////////////////////////////////////
+ // Structures de contrôle
+ ///////////////////////////////////////
+ Console.WriteLine("\n->Structures de contrôle");
+
+ // Structure conditionnelle
+ int j = 10;
+ if (j == 10)
+ {
+ Console.WriteLine("Je serai affiché");
+ }
+ else if (j > 10)
+ {
+ Console.WriteLine("Pas moi");
+ }
+ else
+ {
+ Console.WriteLine("Moi non plus");
+ }
+
+ // Opérateur ternaire
+ // Un simple if/else peut s'écrire :
+ // <condition> ? <valeur si true> : <valeur si false>
+ string isTrue = (true) ? "True" : "False";
+
+ // Boucle while
+ int fooWhile = 0;
+ while (fooWhile < 100)
+ {
+ // 100 passages, de 0 à 99
+ fooWhile++;
+ }
+
+ // Boucle Do While
+ int fooDoWhile = 0;
+ do
+ {
+ // 100 passages, de 0 à 99
+ fooDoWhile++;
+ } while (fooDoWhile < 100);
+
+ // Boucle for
+ // Structure : for(<etat_initial>; <condition>; <pas>)
+ for (int fooFor = 0; fooFor < 10; fooFor++)
+ {
+ // 10 passages, de 0 à 9
+ }
+
+ // La boucle foreach
+ // Structure : foreach(<type_iterateur> <nom_iterateur> in <enumerable>)
+ // Cette boucle est utilisable sur des objets implémentant IEnumerable ou IEnumerable<T>
+ // Toutes les collections du framework .NET (Tableaux, Listes, ...) implémentent ces interfaces.
+ // (Notez que dans l'exemple suivant .ToCharArray() peut être omit car
+ // string implémente IEnumerable)
+ foreach (char character in "Hello World".ToCharArray())
+ {
+ //Itération sur chaque caractère
+ }
+
+ // La structure Switch Case
+ // Un switch fonctionne avec les types : byte, short, char et int.
+ // Les enums sont aussi supportés ainsi que les chaînes de caractères et quelques
+ // classes spéciales basées sur les types primitifs : Character, Byte, Short et Integer.
+ int mois = 3;
+ string moisString;
+ switch (mois)
+ {
+ case 1:
+ moisString = "Janvier";
+ break;
+ case 2:
+ moisString = "Février";
+ break;
+ case 3:
+ moisString = "Mars";
+ break;
+
+ // Vous pouvez assigner plus d'un 'case' à une action
+ // Mais vous ne pouvez pas ajouter une action sans 'break' avant un 'case'
+ // (pour ce faire, il faudrait ajouter explicitement un 'goto case x')
+ case 6:
+ case 7:
+ case 8:
+ moisString = "C'est l'été!";
+ break;
+ default:
+ moisString = "Un autre mois oO";
+ break;
+ }
+
+ ///////////////////////////////////////
+ // conversion de type de donnée et transtypage
+ ///////////////////////////////////////
+
+ // conversion de string vers int
+ // lève une exception en cas d'erreur
+ int.Parse("123"); //retourne la valeur entière de "123"
+
+ // TryParse affecte la valeur par défaut du type en cas d'erreur
+ // dans ce cas : 0
+ int tryInt;
+ if (int.TryParse("123", out tryInt)) // La fonction retourne un booléen
+ Console.WriteLine(tryInt); // => 123
+
+ // conversion d'un entier vers une chaîne de caractères
+ // La classe Convert possède plusieurs méthodes pour faciliter la conversion
+ Convert.ToString(123);
+ // ou
+ tryInt.ToString();
+ }
+
+ ///////////////////////////////////////
+ // CLASSES - voir les définitions à la fin du fichier
+ ///////////////////////////////////////
+
+ public static void Classes()
+ {
+ // voir les déclarations à la fin du fichier
+
+ // Utilisez 'new' pour instancier une classe
+ Bicycle trek = new Bicycle();
+
+ // Appel des méthodes de l'objet
+ trek.SpeedUp(3); // Il est toujours bon d'utiliser des accesseurs
+ trek.Cadence = 100;
+
+ // Affichage de la valeur de retour d'une méthode.
+ Console.WriteLine("trek info: " + trek.Info());
+
+ // Instanciation d'un nouveau PennyFarthing
+ PennyFarthing funbike = new PennyFarthing(1, 10);
+ Console.WriteLine("funbike info: " + funbike.Info());
+
+ Console.Read();
+ }
+
+ // POINT D'ENTRÉE - Une application console doit avoir une méthode main comme point d'entrée
+ public static void Main(string[] args)
+ {
+ OtherInterestingFeatures();
+ }
+
+ //
+ // FONCTIONNALITÉS INTÉRÉSSANTES
+ //
+
+ // SIGNATURE DE METHODE
+ public // Visibilité
+ static // Permet un appel direct par la classe (sans instanciation)
+ int // Type de retour,
+ MethodSignatures(
+ int maxCount, // Premier paramètre, de type int
+ int count = 0, // Valeur par défaut si aucun argument n'est passé
+ int another = 3,
+ params string[] otherParams // Capture tous les arguments passés à la méthode
+ )
+ {
+ return -1;
+ }
+
+ // Des méthodes peuvent avoir le même nom tant que leur signature est unique
+ public static void MethodSignature(string maxCount)
+ {
+ }
+
+ // TYPE GÉNÉRIQUE
+
+ // Les types TKey et TValue sont spécifiés par l'utilisateur lors de l'appel de la fonction
+ // Cette méthode émule SetDefaut de Python
+ public static TValue SetDefault<TKey, TValue>(
+ IDictionary<TKey, TValue> dictionary,
+ TKey key,
+ TValue defaultItem)
+ {
+ TValue result;
+ if (!dictionary.TryGetValue(key, out result))
+ return dictionary[key] = defaultItem;
+ return result;
+ }
+
+ // Vous pouvez limiter les types autorisés
+ public static void IterateAndPrint<T>(T toPrint) where T: IEnumerable<int>
+ {
+ // Nous sommes sûrs de pouvoir itérer, car T implémente IEnumerable<int>
+ foreach (var item in toPrint)
+ // Item sera de type int
+ Console.WriteLine(item.ToString());
+ }
+
+ public static void OtherInterestingFeatures()
+ {
+ // PARAMÈTERES OPTIONNELS
+ MethodSignatures(3, 1, 3, "Des", "Paramètres", "En plus");
+ MethodSignatures(3, another: 3); // affectation explicite, les autres
+ // paramètres ont la valeur par défaut
+
+ // MÉTHODE D'EXTENSION
+ int i = 3;
+ i.Print(); // Définit plus bas
+
+ // TYPES NULLABLE - idéal pour les interactions avec une base de données ou pour les valeurs de retour
+ // Tous les types valeurs peuvent être rendus nullable en les suffixant par '?'
+ // <type>? <nom> = <value>
+ int? nullable = null; // raccourci pour Nullable<int>
+ Console.WriteLine("Nullable variable: " + nullable);
+ bool hasValue = nullable.HasValue; // retourne vrai si la valeur n'est pas null
+
+ // ?? est un sucre syntaxique pour spécifier une valeur par défaut
+ // au cas ou une autre valeur serait nulle
+ int notNullable = nullable ?? 0; // 0
+
+ // VARIABLES IMPLICITEMENT TYPÉES - vous pouvez laisser le compilateur deviner le type d'une variable
+ var magic = "magic est de type string à la compilation. On a toujours un typage fort !";
+ // magic = 9; // ne fonctionnera pas car magic est désormais une chaîne de caractères
+
+ // TYPES GÉNÉRIQUES
+ var agenda = new Dictionary<string, string>() {
+ {"Sarah", "212 555 5555"} // Ajout d'une entrée à notre agenda
+ };
+
+ // Appel de la fonction SetDefault (définie plus haut)
+ Console.WriteLine(SetDefault<string,string>(agenda, "Shaun", "Pas de numéro")); // => Pas de numéro
+ // Notez que vous n'avez pas à spécifier TKey et TValue car le compilateur saura les inférer.
+ Console.WriteLine(SetDefault(agenda, "Sarah", "No Phone")); // => 212 555 5555
+
+ // EXPRESSION LAMBDA - permet d'écrire une fonction en tant qu'expression
+ Func<int, int> square = (x) => x * x; // La dernière expression est la valeur de retour
+ Console.WriteLine(square(3)); // => 9
+
+ // GESTION AUTOMATIQUE DES RESSOURCES - vous permet de manipuler facilement des resources non-managées
+ // La plus part des objets qui accèdent à des ressources non-managées (handle de fichier, périphérique, etc.)
+ // implémentent l'interface IDisposable. L'instruction using prend soin
+ // de libérer les objets IDisposable proprement à votre place.
+ using (StreamWriter writer = new StreamWriter("log.txt"))
+ {
+ writer.WriteLine("Rien à signaler");
+ // À la fin de cette portée les ressources seront libérées.
+ // Même si une exception est levée.
+ }
+
+ // BIBLIOTHÈQUE DE TÂCHES PARALLÈLES (TPL)
+ // http://msdn.microsoft.com/fr-fr/library/dd460717.aspx
+ var websites = new string[] {
+ "http://www.google.com", "http://www.reddit.com",
+ "http://www.shaunmccarthy.com"
+ };
+ var responses = new Dictionary<string, string>();
+
+ // L'exemple suivant exécutera chaque requête dans un thread séparé,
+ // et attendra la fin de chacun d'entre eux avant de continuer
+ Parallel.ForEach(websites,
+ new ParallelOptions() {MaxDegreeOfParallelism = 3}, // maximum de 3 threads
+ website =>
+ {
+ // Fait quelque chose de long
+ using (var r = WebRequest.Create(new Uri(website)).GetResponse())
+ {
+ responses[website] = r.ContentType;
+ }
+ });
+
+ // Ceci ne s'exécutera pas tant que les threads n'auront pas fini leur travail
+ foreach (var key in responses.Keys)
+ Console.WriteLine("{0}:{1}", key, responses[key]);
+
+ // TYPE DYNAMIQUE - idéal pour travailler avec d'autres langages
+ dynamic student = new ExpandoObject();
+ student.FirstName = "Mon prénom"; // Pas besoin de définir l'objet
+
+ // Vous pouvez même ajouter des méthodes (dans cet exemple : la méthode prend une chaîne de caractères et retourne une chaîne de caractères)
+ student.Introduce = new Func<string, string>(
+ (introduceTo) => string.Format("Hey {0}, c'est {1}", student.FirstName, introduceTo));
+ Console.WriteLine(student.Introduce("Beth"));
+
+ // IQUERYABLE<T> - quasiment toutes les collections implémentent cette interface
+ // ce qui permet d'utiliser des méthodes de style 'Filter' / 'Map' / 'Reduce'
+ var bikes = new List<Bicycle>();
+ bikes.Sort(); // Trie le tableau sur place
+ bikes.Sort((b1, b2) => b1.Wheels.CompareTo(b2.Wheels)); // Trie en se basant sur la propriété Wheels
+ var result = bikes
+ .Where(b => b.Wheels > 3) // 'Filter' - enchaînable (retourne un IQueryable du type précédent)
+ .Where(b => b.IsBroken && b.HasTassles)
+ .Select(b => b.ToString()); // 'Map' - on retourne le .ToString() de chaque élément filtré,
+ // le résultat est un IQueryable<string>
+
+ var sum = bikes.Sum(b => b.Wheels); // 'Reduce' - fait la somme de tous les Wheels de la liste
+
+ // Creation d'une liste d'objet anonymes basés sur des paramètres de la classe Bike
+ var bikeSummaries = bikes.Select(b=>new { Name = b.Name, IsAwesome = !b.IsBroken && b.HasTassles });
+ // Le compilateur peut inférer le type de ces objets anonymes, permettant à certains IDE d'effectuer
+ // des autos-complétion.
+ foreach (var bikeSummary in bikeSummaries.Where(b => b.IsAwesome))
+ Console.WriteLine(bikeSummary.Name);
+
+
+ // ASPARALLEL
+ // C'est ici que les choses se compliquent - un mélange de LINQ et de TPL
+ var threeWheelers = bikes.AsParallel().Where(b => b.Wheels == 3).Select(b => b.Name);
+ // La ligne précédente s'exécute en parallèle ! Des threads seront gérés automatiquement
+ // et les données y seront réparties. Idéal sur de grosses données (et si votre
+ // machine dispose de plusieurs coeurs)
+
+
+ // LINQ - lie une source de données à des objets IQueryable<T>
+ // ex : LindToSql => liaison avec une base de données, LinqToXml => liaison avec un document xml
+ var db = new BikeRespository();
+
+ // l'exécution est décalée, ce qui est préférable quand on travaille sur une base données
+ var filter = db.Bikes.Where(b => b.HasTassles); // pas de requête exécutée
+ if (42 > 6) // Vous pouvez continuer à affiner la recherche
+ filter = filter.Where(b => b.IsBroken); // pas de requête exécutée
+
+ var query = filter
+ .OrderBy(b => b.Wheels)
+ .ThenBy(b => b.Name)
+ .Select(b => b.Name); // toujours pas de requête exécutée
+
+ // Maintenant la requête est exécutée, mais retourne des données uniquement au fil de l'itération
+ foreach (string bike in query)
+ Console.WriteLine(result);
+
+ }
+
+ } // Fin de la classe LearnCSharp
+
+ // Il est possible d'inclure plusieurs classes dans un fichier .cs
+
+ public static class Extensions
+ {
+ // EXTENSION DE FONCTIONS
+ public static void Print(this object obj)
+ {
+ Console.WriteLine(obj.ToString());
+ }
+ }
+
+ // Syntaxe de déclaration de classe :
+ // <public/private/protected/internal> class <class name>{
+ // // champs, constructeurs, fonctions
+ // // tout est déclaré et implémenté à l'intérieur
+ // }
+
+ public class Bicycle
+ {
+ // Propriétés et variable de la classe
+ public int Cadence // Public : peut être accédé de partout
+ {
+ get // get - définit une méthode pour lire la propriété
+ {
+ return _cadence;
+ }
+ set // set - définit une méthode pour affecter une valeur à la propriété
+ {
+ _cadence = value; // 'value' est la valeur passée en argument au setteur
+ }
+ }
+ private int _cadence;
+
+ protected virtual int Gear // Protected : accessible depuis la classe et ses classes filles
+ {
+ get; // crée une propriété automatique, pas besoin de créer une variable de stockage
+ set;
+ }
+
+ internal int Wheels // Internal : accessible depuis l'assembly
+ {
+ get;
+ private set; // Il est possible de choisir la portée d'un accesseur
+ }
+
+ int _speed; // Par défaut tout est privé au sein d'une classe : accessible uniquement depuis la classe
+ // on peut ajouter explicitement le mot clé 'private'
+
+ public string Name { get; set; }
+
+
+ // Enum est un type valeur formé par un ensemble de constantes nommées
+ // C'est simplement une manière de mettre un nom sur une valeur (int par défaut).
+ // Les types compatibles pour un enum sont : byte, sbyte, short, ushort, int, uint, long et ulong.
+ // Un enum ne peut pas contenir deux fois la même valeur
+ public enum BikeBrand
+ {
+ AIST,
+ BMC,
+ Electra = 42, // il est possible de donner explicitement une valeur
+ Gitane // 43
+ }
+ // Nous avons défini cet enum à l'intérieur de la classe Bicycle, c'est donc un type imbriqué
+ // Pour le référencer à l'extérieur, il faudra utiliser Bicycle.BikeBrand
+
+ public BikeBrand Brand; // Après avoir déclaré notre type enum, on peut créer un champ de ce type
+
+ // Les membres statiques appartiennent à une classe plutôt qu'à une instance particulière
+ // Il est possible d'y accéder sans passer par un objet :
+ // ex : Console.WriteLine("Bicycles créés : " + Bicycle.bicyclesCreated);
+ static public int BicyclesCreated = 0;
+
+ // Les valeurs en lecture seule sont affectées lors de l'exécution
+ // Elles ne peuvent être assignées que lors de leur déclaration ou dans un constructeur
+ readonly bool _hasCardsInSpokes = false; // variable en lecture et privée
+
+ // Les constructeurs sont un moyen de créer des objets
+ // Voici un constructeur par défaut (pas d'arguments)
+ public Bicycle()
+ {
+ this.Gear = 1; // accès aux membres de la classe via le mot clé this
+ Cadence = 50; // qui est souvent implicite
+ _speed = 5;
+ Name = "Bontrager";
+ Brand = BikeBrand.AIST;
+ BicyclesCreated++;
+ }
+
+ // Voici un constructeur spécifique (qui prend des arguments)
+ public Bicycle(int startCadence, int startSpeed, int startGear,
+ string name, bool hasCardsInSpokes, BikeBrand brand)
+ : base() // possibilité d'appeler le constructeur de la classe mère (ici Object)
+ {
+ Gear = startGear;
+ Cadence = startCadence;
+ _speed = startSpeed;
+ Name = name;
+ _hasCardsInSpokes = hasCardsInSpokes;
+ Brand = brand;
+ }
+
+ // Les constructeurs peuvent s'enchaîner
+ public Bicycle(int startCadence, int startSpeed, BikeBrand brand) :
+ this(startCadence, startSpeed, 0, "big wheels", true, brand)
+ {
+ }
+
+ // Syntaxe de méthode :
+ // <public/private/protected> <type de retour> <nom de methode>(<args>)
+
+ // Les classes peuvent implémenter des accesseurs pour leurs champs
+ // ou implémenter des propriétés (c'est la méthode dominante en C#)
+
+ // Les paramètres de méthodes peuvent avoir des valeurs par défaut
+ // Dans ce cas, la méthode peut être appelée sans arguments
+ public void SpeedUp(int increment = 1)
+ {
+ _speed += increment;
+ }
+
+ public void SlowDown(int decrement = 1)
+ {
+ _speed -= decrement;
+ }
+
+ // Les propriétés se chargent de lire/modifier des valeurs
+ // elles peuvent être en lecture(get), en écriture(set) ou les deux
+ private bool _hasTassles; // variable privée
+ public bool HasTassles // propriété publique
+ {
+ get { return _hasTassles; }
+ set { _hasTassles = value; }
+ }
+
+ // Il est possible de définir une propriété automatique sur une ligne
+ // cette syntaxe créera une variable de stockage automatiquement.
+ // Il est possible de modifier l'accèsibilité des getter/setter pour limiter leur utilisation
+ public bool IsBroken { get; private set; }
+
+ // La même chose sur plusieurs lignes
+ public int FrameSize
+ {
+ get;
+ // Notez que seule la classe Bicycle peut changer la valeur de FrameSize
+ private set;
+ }
+
+ // Méthode qui affiche la valeur des champs de cet objet
+ public virtual string Info()
+ {
+ return "Gear: " + Gear +
+ " Cadence: " + Cadence +
+ " Speed: " + _speed +
+ " Name: " + Name +
+ " Cards in Spokes: " + (_hasCardsInSpokes ? "yes" : "no") +
+ "\n------------------------------\n"
+ ;
+ }
+
+ // Les méthodes peuvent aussi être statiques. Utile pour les méthodes d'aide.
+ public static bool DidWeCreateEnoughBycles()
+ {
+ // À l'intérieur d'une méthode statique on ne peut que référencer des membres statiques !
+ return BicyclesCreated > 9000;
+ } // Si votre classe n'a que des membres statiques, marquez la comme statique
+
+ } // fin de la classe Bicycle
+
+ // PennyFarthing est une classe dérivée de Bicycle
+ class PennyFarthing : Bicycle
+ {
+ // Appel au constructeur de la classe mère
+ public PennyFarthing(int startCadence, int startSpeed) :
+ base(startCadence, startSpeed, 0, "PennyFarthing", true, BikeBrand.Electra)
+ {
+ }
+
+ protected override int Gear
+ {
+ get
+ {
+ return 0;
+ }
+ set
+ {
+ // Lève une exception
+ throw new ArgumentException("Impossible de modifier Gear sur un PennyFarthing");
+ }
+ }
+
+ public override string Info()
+ {
+ string result = "PennyFarthing bicycle ";
+ result += base.ToString(); // Appel à la version de base de cette méthode
+ return result;
+ }
+ }
+
+ // Les interfaces contiennent uniquement la signature de leurs membres, sans implémentation.
+ interface IJumpable
+ {
+ void Jump(int meters); // Tous les membres d'interface sont publics par défaut
+ }
+
+ interface IBreakable
+ {
+ bool Broken { get; } // Les interfaces peuvent contenir des propriétés,
+ // des méthodes et des évènements
+ }
+
+ // Une classe ne peut hériter que d'une seule autre classe, mais peut implémenter plusieurs interfaces
+ class MountainBike : Bicycle, IJumpable, IBreakable
+ {
+ int damage = 0;
+
+ public void Jump(int meters)
+ {
+ damage += meters;
+ }
+
+ public bool Broken
+ {
+ get
+ {
+ return damage > 100;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Utilisé pour illustrer la connexion à une base donnée dans l'exemple LinqToSql
+ /// L'approche code first d'EntityFramework est très pratique (un peu comme ActiveRecord de Ruby)
+ /// http://msdn.microsoft.com/fr-fr/data/jj193542.aspx
+ /// </summary>
+ public class BikeRespository : DbSet
+ {
+ public BikeRespository()
+ : base()
+ {
+ }
+
+ public DbSet<Bicycle> Bikes { get; set; }
+ }
+} // Fin du namespace
+```
+
+## Sujets non-abordés
+
+ * Flags
+ * Attribus
+ * Propriétés statiques
+ * Exceptions, Abstraction
+ * ASP.NET (Web Forms/MVC/WebMatrix)
+ * Winforms
+ * Windows Presentation Foundation (WPF)
+
+## Lectures Complémentaires
+
+ * [DotNetPerls](http://www.dotnetperls.com)
+ * [C# in Depth](http://manning.com/skeet2)
+ * [Programming C#](http://shop.oreilly.com/product/0636920024064.do)
+ * [LINQ](http://shop.oreilly.com/product/9780596519254.do)
+ * [MSDN Library](http://msdn.microsoft.com/en-us/library/618ayhy6.aspx)
+ * [ASP.NET MVC Tutorials](http://www.asp.net/mvc/tutorials)
+ * [ASP.NET Web Matrix Tutorials](http://www.asp.net/web-pages/tutorials)
+ * [ASP.NET Web Forms Tutorials](http://www.asp.net/web-forms/tutorials)
+ * [Windows Forms Programming in C#](http://www.amazon.com/Windows-Forms-Programming-Chris-Sells/dp/0321116208)
+
+[Convention de codage C#](http://msdn.microsoft.com/library/vstudio/ff926074)
diff --git a/fr-fr/haskell.html.markdown b/fr-fr/haskell.html.markdown
new file mode 100644
index 00000000..989db1d5
--- /dev/null
+++ b/fr-fr/haskell.html.markdown
@@ -0,0 +1,431 @@
+---
+language: haskell
+contributors:
+ - ["Adit Bhargava", "http://adit.io"]
+translators:
+ - ["David Baumgartner", "http://davidbaumgartner.ch"]
+lang: fr-fr
+filename: learnhaskell-fr.hs
+---
+
+Haskell a été conçu pour être un langage fonctionnel pur et maniable. Il est connu pour ses monades et son système de types, mais je n'ai cesse d'y revenir pour son élégance. Pour moi, Haskell fait de la programmation une joie.
+
+```haskell
+-- Un commentaire en une ligne commence avec deux tirets.
+{- Un commentaire sur plusieurs lignes peut être contenu dans
+un bloc de cette façon.
+-}
+
+----------------------------------------------------
+-- 1. Types de données primitifs et opérateurs
+----------------------------------------------------
+
+-- Vous avez les nombres
+3 -- 3
+
+-- Les maths sont comme vous vous y attendez
+1 + 1 -- 2
+8 - 1 -- 7
+10 * 2 -- 20
+35 / 5 -- 7.0
+
+-- La division n'est pas entière par défaut
+35 / 4 -- 8.75
+
+-- division entière
+35 `div` 4 -- 8
+
+-- Les booléens sont primitifs
+True
+False
+
+-- Opérations avec les booléens
+not True -- False
+not False -- True
+1 == 1 -- True
+1 /= 1 -- False
+1 < 10 -- True
+
+-- Dans les exemples plus hauts, `not` est une fonction qui prend une valeur.
+-- Haskell n'a pas besoin de parenthèses pour appeler une fonction... tous
+-- les arguments sont juste listés après la fonction. Le schéma général est
+-- donc :
+-- func arg1 arg2 arg3...
+-- Voyez la section sur les fonctions pour savoir comment écrire les vôtres.
+
+-- Caractères et chaînes de caractère
+"Ceci est une chaîne de caractère."
+'a' -- caractère
+'Vous ne pouvez pas utiliser des apostrophes pour les chaînes de caractère.' -- erreur !
+
+-- Les chaînes peuvent être concaténées
+"Hello " ++ "world!" -- "Hello world!"
+
+-- Une chaîne de caractère est *réellement* une liste
+"Ceci est une chaîne." !! 0 -- 'C'
+
+
+----------------------------------------------------
+-- Listes et tuples
+----------------------------------------------------
+
+-- Tous les éléments d'une liste doit avoir le même type.
+-- les deux lignes suivantes sont semblables
+[1, 2, 3, 4, 5]
+[1..5]
+
+-- Il y a aussi des listes infinies en Haskell !
+[1..] -- une liste de tous les nombres naturels
+
+-- Les listes infinies fonctionnent parce que Haskell est « paresseux »:
+-- ça veut dire qu'il n'évalue que ce qui a besoin de l'être. Vous pouvez
+-- donc vous demander le 1000e élément de votre liste et il vous le donnera :
+
+[1..] !! 999 -- 1000
+
+-- Et là, Haskell a évalué les éléments 1 à 1000 de la liste... mais le reste
+-- de cette liste « infinie » n'existe pas encore ! En fait, Haskell ne va jamais
+-- le faire à moins qu'il ne le doive.
+
+-- Adjoindre deux listes
+[1..5] ++ [6..10]
+
+-- ajouter au début de la liste
+0:[1..5] -- [0, 1, 2, 3, 4, 5]
+
+-- l'indice d'une liste
+[0..] !! 5 -- 5
+
+-- d'autres opérations sur les listes
+head [1..5] -- 1
+tail [1..5] -- [2, 3, 4, 5]
+init [1..5] -- [1, 2, 3, 4]
+last [1..5] -- 5
+
+--liste en compréhension
+[x*2 | x <- [1..5]] -- [2, 4, 6, 8, 10]
+
+--avec un conditionnel
+[x*2 | x <- [1..5], x*2 > 4] -- [6, 8, 10]
+
+-- Chaque élément d'un tuple peut être d'un type différent, mais un
+-- tuple a une longueur fixée.
+-- Un tuple :
+("haskell", 1)
+
+-- accéder aux éléments d'un tuple
+fst ("haskell", 1) -- "haskell"
+snd ("haskell", 1) -- 1
+
+----------------------------------------------------
+-- 3. Functions
+----------------------------------------------------
+-- Une simple fonction qui prend deux paramètres
+add a b = a + b
+
+-- Notez que si vous utilisez ghci (l'interpréteur Haskell)
+-- vous devrez utiliser `let`. Par exemple :
+-- let add a b = a + b
+
+-- Utiliser une fonction
+add 1 2 -- 3
+
+-- Vous pouvez également mettre le nom de la fonction entre les
+-- deux arguments avec des accents graves :
+1 `add` 2 -- 3
+
+-- Vous pouvez également définir des fonctions qui n'ont pas de
+-- lettres ! Ça vous laisse créer vos propres opérateurs ! Voilà
+-- un opérateur qui fait une division entière :
+(//) a b = a `div` b
+35 // 4 -- 8
+
+-- Gardes : Une façon de gérer la valeur de vos arguments en amont
+fib x
+ | x < 2 = x
+ | otherwise = fib (x - 1) + fib (x - 2)
+
+-- Le filtrage par motif est similaire. Là, on a donné trois
+-- définitions différentes de `fib`. Haskell appellera automatiquement
+-- la première fonction qui correspond au motif de la valeur.
+fib 1 = 1
+fib 2 = 2
+fib x = fib (x - 1) + fib (x - 2)
+
+-- Filtrage par motif sur un tuple.
+foo (x, y) = (x + 1, y + 2)
+
+-- Filtrage par motif sur des listes. Ici, `x` est le premier
+-- élément de la liste, et `xs` le reste. On peut écrire notre
+-- propre fonction `map` :
+myMap func [] = []
+myMap func (x:xs) = func x:(myMap func xs)
+
+-- Les fonctions anonymes sont créées avec des barres obliques
+-- inverses, suivies de tous les arguments.
+myMap (\x -> x + 2) [1..5] -- [3, 4, 5, 6, 7]
+
+-- Une utilisation de fold (appelée `inject` dans quelques autres
+-- langages) avec comme paramètre une fonction anonyme.
+-- `foldl1` veut dire fold left -- soit littéralement pli gauche --
+-- et utilise la première valeur de la liste comme accumulateur.
+foldl1 (\acc x -> acc + x) [1..5] -- 15
+
+----------------------------------------------------
+-- 4. Plus de fonctions
+----------------------------------------------------
+
+-- curryfication : si vous n'appliquez pas tous les arguments à une
+-- fonction, elle devient « curryfiée ». Ça veut dire qu'elle retourne
+-- une fonction qui prend le reste des arguments.
+
+add a b = a + b
+foo = add 10 -- foo est une fonction qui prend un nombre et y ajoute 10
+foo 5 -- 15
+
+-- Une autre façon de l'écrire
+foo = (+10)
+foo 5 -- 15
+
+-- Composition de fonctions
+-- la fonction (.) enchaîne deux fonctions.
+-- Par exemple, on a foo qui est une fonction qui prend une valeur, y ajoute
+-- 10 et multiplie ce résultat par 5, et ensuite retourne la valeur finale.
+foo = (*5) . (+10)
+
+-- (5 + 10) * 5 = 75
+foo 5 -- 75
+
+-- fixation de priorité
+-- Haskell a une autre fonction appelée `$`. Elle peut changer la priorité
+-- de sorte que tout ce qu'il y a à sa gauche est calculé d'abord et ensuite
+-- appliqué à tout ce qu'il y a à droite. Vous pouvez utiliser `.` et `$`
+-- pour vous débarrasser de beaucoup de parenthèses :
+
+-- avant
+(even (fib 7)) -- False
+
+-- ensuite
+even . fib $ 7 -- False
+
+----------------------------------------------------
+-- 5. Signature de type
+----------------------------------------------------
+
+-- Haskell a un système de types très strict : par exemple, tout a un type.
+
+-- Quelques types simples :
+5 :: Integer
+"hello" :: String
+True :: Bool
+
+-- Les fonctions ont également des types.
+-- `not` prend un booléen et retourne un booléen.
+-- not :: Bool -> Bool
+
+-- Voilà une fonction qui prend deux paramètres.
+-- add :: Integer -> Integer -> Integer
+
+-- Quand vous définissez une valeur (souvenez-vous, tout est valeur en
+-- Haskell), une bonne pratique est d'écrire son type explicitement
+double :: Integer -> Integer
+double x = x * 2
+
+----------------------------------------------------
+-- 6. Flux de contrôle et structures conditionnelles
+----------------------------------------------------
+
+-- structure conditionnelle if
+haskell = if 1 == 1 then "awesome" else "awful" -- haskell = "awesome"
+
+-- les structures if peuvent être écrites sur plusieurs lignes
+haskell = if 1 == 1
+ then "awesome"
+ else "awful"
+
+-- les structures case : voilà comment vous pourriez analyser les arguments de
+-- ligne de commande
+case args of
+ "help" -> printHelp
+ "start" -> startProgram
+ _ -> putStrLn "bad args"
+
+
+-- Haskell n'a pas de boucles parce qu'il utilise la récursion.
+-- `map` applique une fonction sur chaque élément d'une liste
+
+map (*2) [1..5] -- [2, 4, 6, 8, 10]
+
+-- vous pouvez créer une fonction `for` en utilisant `map`
+for array func = map func array
+
+-- et l'utiliser
+for [0..5] $ \i -> show i
+
+-- nous aurions pu l'écrire également ainsi
+for [0..5] show
+
+-- vous pouvez utiliser foldl et foldr pour
+-- réduire une liste
+-- foldl <fonction> <valeur initiale> <liste>
+foldl (\x y -> 2*x + y) 4 [1,2,3] -- 43
+
+-- C'est donc la même chose que
+(2 * (2 * (2 * 4 + 1) + 2) + 3)
+
+-- foldl évalue de gauche à droite, foldr
+-- de droite à gauche
+foldr (\x y -> 2*x + y) 4 [1,2,3] -- 16
+
+-- Et c'est équivalent à
+(2 * 3 + (2 * 2 + (2 * 1 + 4)))
+
+----------------------------------------------------
+-- 7. Types de données
+----------------------------------------------------
+
+-- Vous pouvez écrire vos propres types de données en Haskell
+
+data Couleur = Rouge | Bleu | Vert
+
+-- Et maintenant l'utiliser dans une fonction
+
+
+say :: Couleur -> String
+say Rouge = "Vous êtes Rouge !"
+say Bleu = "Vous êtes Bleu !"
+say Vert = "Vous êtes Vert !"
+
+-- Vos types peuvent également avoir des paramètres
+
+data Maybe a = Nothing | Just a
+
+-- Tous les exemples ci-dessous sont issus du type Maybe
+Just "hello" -- of type `Maybe String`
+Just 1 -- of type `Maybe Int`
+Nothing -- of type `Maybe a` for any `a`
+
+----------------------------------------------------
+-- 8. Haskell IO
+----------------------------------------------------
+
+-- Tandis que l'IO ne peut pas être totalement expliqué pleinement
+-- sans que les monades ne le soient, il n'est pas difficile
+-- d'expliquer suffisamment pour commencer.
+
+-- Quand un programme en Haskell est exécuté, la fonction `main`
+-- est appelée. Il doit retourner une valeur de type `IO ()`.
+-- Par exemple :
+
+main :: IO ()
+main = putStrLn $ "Bonjour, le ciel ! " ++ (say Blue)
+-- putStrLn a comme type String -> IO ()
+
+-- La façon la plus simple pour faire de l'IO est de faire un programme
+-- fonction de String vers String. La fonction
+-- interact :: (String -> String) -> IO ()
+-- prend un texte, applique une fonction et affiche le résultat.
+
+countLines :: String -> String
+countLines = show . length . lines
+
+main' = interact countLines
+
+-- Vous pouvez considérer qu'une valeur de type `IO ()` représente
+-- une séquence d'actions que l'ordinateur exécute, un peu comme
+-- dans un langage impératif. On peut utiliser la structure `do`
+-- pour enchaîner des actions. Par exemple :
+
+sayHello :: IO ()
+sayHello = do
+ putStrLn "Quel est ton nom ?"
+ name <- getLine -- prend une ligne et assigne sa valeur à `name`
+ putStrLn $ "Salut, " ++ name
+
+-- Exercice : écrire votre propre version d'`interact` qui ne fait
+-- que de lire une ligne d'entrée.
+
+-- Le code de `sayHello` ne sera jamais exécuté, cependant. La seule
+-- action qui sera exécutée est la valeur de `main`.
+-- Pour lancer `sayHello`, commentez l'ancienne définition de `main`
+-- et remplacez-le par :
+-- main = sayHello
+
+-- Essaions de mieux comprendre comment la fonction `getLine` que
+-- nous venons d'utiliser. Son type est :
+-- getLine :: IO String
+-- vous pouvez considérer le type `IO a` comme un programme que
+-- le programme va générer comme une valeur de type `a` quand
+-- il sera exécuté. On peut l'enregistrer et la réutiliser en
+-- utilisant `<-`. On peut aussi faire nos propres actions
+-- de type `IO String` :
+
+action :: IO String
+action = do
+ putStrLn "C'est une ligne. Heu"
+ input1 <- getLine
+ input2 <- getLine
+ -- Le type de la structure `do` est celui de sa dernière ligne.
+ -- `return` n'est pas un mot clef, mais simplement une fonction.
+ return (input1 ++ "\n" ++ input2) -- return :: String -> IO String
+
+-- On peut maintenant l'utiliser comme on a utilisé `getLine`
+-- tout à l'heure
+
+main'' = do
+ putStrLn "Je vais afficher deux lignes !"
+ result <- action
+ putStrLn result
+ putStrLn "C'était tout !"
+
+-- Le type `IO` est un exemple de « monade ». La façon dont Haskell utilise
+-- une monade pour faire de l'IO lui permet d'être purement fonctionnel. N'importe
+-- quelle fonction qui interagit avec le « monde extérieur » (c'est à dire fait de l'IO)
+-- devient marqué comme `IO` dans la signature de son type. Ça nous montre
+-- quelles fonctions sont « pures » (n'interagissent pas avec le monde extérieur
+-- ou ne changent pas d'état) et quelles fonctions ne le sont pas.
+
+-- C'est une fonctionnalité très puissante, car il est facile d'exécuter
+-- des fonctions pures simultanément, et donc la concurrence en Haskell
+-- est très facile.
+
+
+----------------------------------------------------
+-- 9. Le REPL de Haskell
+----------------------------------------------------
+
+-- Lancer le REPL en tapant `ghci`.
+-- Vous pouvez maintenant taper du code Haskell.
+-- Toutes les nouvelles valeurs peuvent être crées
+-- avec `let` :
+
+let foo = 5
+
+-- Vous pouvez voir le type de n'importe quelle valeur avec `:t` :
+
+>:t foo
+foo :: Integer
+
+-- Vous pouvez également lancer des actions de type `IO ()`
+
+> sayHello
+Quel est ton nom ?
+Ami
+Salut, Ami !
+
+```
+
+Et Haskell ne se limite pas à ça, on trouve encore par exemple les classes de types et les monades. Il y a beaucoup de raisons qui font que coder en Haskell est si *fun*. Je vous laisse avec un dernier exemple : une implémentation de quicksort :
+
+```haskell
+qsort [] = []
+qsort (p:xs) = qsort lesser ++ [p] ++ qsort greater
+ where lesser = filter (< p) xs
+ greater = filter (>= p) xs
+```
+
+Haskell facile à installer. Téléchargez-le [ici](http://www.haskell.org/platform/).
+
+Vous pouvez trouver une approche beaucoup plus douce avec les excellents
+[Learn you a Haskell](http://lyah.haskell.fr/) ou
+[Real World Haskell (en)](http://book.realworldhaskell.org/).
diff --git a/fr-fr/lua-fr.html.markdown b/fr-fr/lua-fr.html.markdown
new file mode 100644
index 00000000..922d6ebc
--- /dev/null
+++ b/fr-fr/lua-fr.html.markdown
@@ -0,0 +1,449 @@
+---
+language: lua
+filename: learnlua-fr.lua
+contributors:
+ - ["Tyler Neylon", "http://tylerneylon.com/"]
+translators:
+ - ["Roland Yonaba", "http://github.com/Yonaba"]
+lang: fr-fr
+---
+
+```lua
+-- Les commentaires unilignes commencent par un double tiret.
+
+--[[
+ Les doubles crochets à la suite du double tiret
+ permettent d'insérer des commentaires multilignes.
+--]]
+
+----------------------------------------------------
+-- 1. Variables et contrôle d'exécution.
+----------------------------------------------------
+
+num = 42 -- Tous les nombres sont de type double.
+-- Rassurez vous cependant, les doubles stockés sur 64-bits
+-- en réservent 52 pour la valeur exacte des entiers. La
+-- précision n'est donc pas un problème pour tout entier qui
+-- peut être codé sur moins de 52 bits.
+
+s = 'walternate' -- Chaines de caractères immuables comme en Python.
+t = "une chaine avec des guillemets doubles"
+u = [[les double crochets permettent
+ d'avoir une chaine de caractères
+ sur plusieurs lignes.]]
+t = nil -- Affecte la valeur nulle à t; Lua possède un ramasse-miettes
+
+-- Le do/end définit un bloc de code
+while num < 50 do
+ num = num + 1 -- Pas d'opérateurs de type ++ ou +=.
+end
+
+-- Les structures en if:
+if num > 40 then
+ print('supérieur à 40')
+elseif s ~= 'walternate' then -- ~= : est différent de.
+ -- Le test d'égalité se fait avec == comme en Python.
+ io.write('inférieur à 40\n') -- Écrit par defaut sur la sortie stdout.
+else
+ -- Les variables sont globales par défaut.
+ thisIsGlobal = 5 -- le style camelCase est courant.
+
+ -- Une variable locale est déclarée avec le mot-clé local:
+ local line = io.read() -- Permet de lire la ligne suivante dans stdin.
+
+ -- .. est l'opérateur de concaténation:
+ print("L'hiver approche, " .. line)
+end
+
+-- Les variables non définies reçoivent par défaut la valeur nil.
+foo = anUnknownVariable -- Maintenant, foo = nil.
+
+aBoolValue = false
+
+-- Seuls nil et false sont des valeurs fausses.
+-- Mais 0 et '' sont des valeurs vraies!
+if not aBoolValue then print('etait faux') end
+
+-- L'évaluation du 'or' et du 'and' est court-circuité.
+-- Comme avec les ternaires du C et du JS: a?b:c
+ans = aBoolValue and 'oui' or 'non' --> 'non'
+
+karlSum = 0
+for i = 1, 100 do -- Les bornes sont incluses dans l'intervalle.
+ karlSum = karlSum + i
+end
+
+-- Utilisez "100, 1, -1" pour la décrémentation:
+fredSum = 0
+for j = 100, 1, -1 do fredSum = fredSum + j end
+
+-- En général, l'intervalle est début, fin[, pas].
+
+-- Un autre type de boucle:
+repeat
+ print('the way of the future')
+ num = num - 1
+until num == 0
+
+
+----------------------------------------------------
+-- 2. Fonctions.
+----------------------------------------------------
+
+function fib(n)
+ if n < 2 then return n end
+ return fib(n - 2) + fib(n - 1)
+end
+
+-- Lua implémente les fermetures et les fonctions anonymes:
+function adder(x)
+ -- La fonction retournée est créée lorsque adder est appelé
+ -- et elle se rappelle de la valeur de x.
+ return function (y) return x + y end
+end
+a1 = adder(9)
+a2 = adder(36)
+print(a1(16)) --> 25
+print(a2(64)) --> 100
+
+-- Les valeurs de retour, les appels de fonction, les assignations
+-- supportent tous les listes qui peuvent ne pas correspondre en longueur.
+-- Dans ce cas, les variables à assigner en supplément reçoivent nil
+-- tandis que les valeurs à attribuer en supplément sont ignorées
+
+x, y = 1, 2 -- x = 1 et y = 2
+x, y, z = 1, 2 -- x = 1, y = 2 et z = nil
+x, y, z = 1, 2, 3, 4 -- x = 1, y = 2, z = 3, et 4 est ignoré.
+
+function bar(a, b, c)
+ print(a, b, c)
+ return 4, 8, 15, 16, 23, 42
+end
+
+x, y = bar('zaphod') --> affiche "zaphod nil nil"
+-- x = 4, y = 8, les valeurs 15 à 42 sont ignorées.
+
+-- Les fonctions sont des valeurs de première classe
+-- et peuvent être locales/globales.
+-- Les déclarations suivantes sont identiques:
+function f(x) return x * x end
+f = function (x) return x * x end
+
+-- Il en va de même pour les déclarations suivantes:
+local function g(x) return math.sin(x) end
+local g = function(x) return math.sin(x) end
+-- Sauf que pour le dernier cas, même si local g = function(x)
+-- est équivalent à local function g(x), il n'est pas possible
+-- de faire appel à g à l'intérieur du corps de la fonction (récursion)
+
+-- À moins de déclarer la fonction auparavant:
+local g; g = function (x) return math.sin(x) end
+
+-- À propos, les fonctions trigonométriques interprètent
+-- leurs arguments en radians.
+print(math.cos(math.pi)) -- affiche "-1"
+print(math.sin(math.pi)) -- affiche "0"
+
+-- Lorsqu'une fonction est appelée avec un seul argument qui est une chaine,
+-- les parenthèses peuvent être omises:
+print 'hello' -- équivalent à print('hello').
+
+-- Lorsqu'une fonction est appelée avec un seul argument qui est une table,
+-- les parenthèses peuvent aussi être omises.
+print {} -- équivalent à print({}).
+
+
+----------------------------------------------------
+-- 3. Tables.
+----------------------------------------------------
+
+-- Tables = Seule structure de données en Lua;
+-- Ce sont des listes assotiatives.
+-- Elles sont similaires aux tables PHP ou aux objets JS :
+-- des tables-dictionnaires que l'on peut utiliser en tant que listes.
+
+-- Tables en tant que dictionnaires:
+
+-- Les clés sont des chaines de caractères par défaut:
+t = {key1 = 'valeur1', key2 = false}
+
+-- Elles peuvent être indexées avec la notation en point, comme en JS:
+print(t.key1) -- Affiche "valeur1".
+t.newKey = {} -- Ajoute une nouvelle paire clé/valeur.
+t.key2 = nil -- Supprime la clé "key2" de la table.
+
+-- Notation littérale pour toute valeur non nulle en tant que clé:
+u = {['@!#'] = 'qbert', [{}] = 1729, [6.28] = 'tau'}
+print(u[6.28]) -- affiche "tau"
+
+-- La correspondance des clés se fait par valeur pour
+-- les nombres et les chaines, mais par référence pour les tables.
+a = u['@!#'] -- a = 'qbert'.
+b = u[{}] -- On pourrait s'attendre à 1729, mais l'on obtient nil:
+-- b = nil car la clé utilisée n'est pas le même objet que celui
+-- utilisé pour stocker la valeur originale 1729.
+
+-- Si une fonction prend en argument une seule table, l'on peut
+-- omettre les parenthèses:
+function h(x) print(x.key1) end
+h{key1 = 'Sonmi~451'} -- Affiche 'Sonmi~451'.
+
+for key, val in pairs(u) do -- Parcours d'une table.
+ print(key, val)
+end
+
+-- _G est une table spéciale contenant toutes les variables globales,
+-- et donc elle même.
+print(_G['_G'] == _G) -- Affiche 'true'.
+
+-- Tables en tant que listes:
+
+-- De manière implicite, les clés sont des nombres entiers:
+v = {'value1', 'value2', 1.21, 'gigawatts'}
+for i = 1, #v do -- #v retourne la taille de la table v si elle est une liste.
+ print(v[i]) -- Attention, en Lua, les indices commencent à 1!
+end
+-- Il n'existe pas vraiment de type 'liste' en Lua, v est juste
+-- une table avec des clés qui sont des nombres entiers consécutifs
+-- commençant à 1. Lua le traite comme étant une liste.
+
+----------------------------------------------------
+-- 3.1 Métatables and métaméthodes.
+----------------------------------------------------
+
+-- Une table peut avoir une métatable qui confère à la table
+-- un patron/prototype de conception (surcharge d'opération). Nous verrons
+-- dans la suite comment les métatables imitent le prototypage du JS.
+
+f1 = {a = 1, b = 2} -- Représente la fraction a/b.
+f2 = {a = 2, b = 3}
+
+-- Ceci créée une erreur:
+-- s = f1 + f2
+
+metafraction = {}
+function metafraction.__add(f1, f2)
+ local sum = {}
+ sum.b = f1.b * f2.b
+ sum.a = f1.a * f2.b + f2.a * f1.b
+ return sum
+end
+
+setmetatable(f1, metafraction)
+setmetatable(f2, metafraction)
+
+s = f1 + f2 -- appèle __add(f1, f2) de la métatable de f1
+
+-- f1, f2 ne possèdent pas de clé qui pointent vers leur métatable, comme
+-- avec les prototypes en JS. Mais l'on peut utiliser getmetatable(f1).
+-- La métatable est une table normale avec des clés prédéfinies, comme __add.
+
+-- Mais la ligne suivante génère une erreur puisque s n'a pas de métatable:
+-- t = s + s
+-- En implémentant de l'orienté objet, comme nous le verrons par la suite,
+-- le problème est résolu.
+
+-- Une clé __index dans une métatable mt surcharge l'indexation dans sa table t
+-- si la clé est absente de cette table t:
+defaultFavs = {animal = 'gru', food = 'donuts'}
+myFavs = {food = 'pizza'}
+setmetatable(myFavs, {__index = defaultFavs})
+eatenBy = myFavs.animal -- Affiche "gru"! merci à la métatable!
+
+-- Ainsi donc, un accès direct à une valeur dans une table via une clé
+-- inexistante (ce qui normalement retourne "nil") conduira à exploiter
+-- le champ __index de la métatable. Cela peut être récursif.
+
+-- Le champ __index peut aussi être une fonction (tbl, clé)
+-- ce qui permet une gestion plus souple des indexations.
+
+-- Les clés __index, __add,... sont appelées métaméthodes.
+-- En voici la liste complète:
+
+-- __add(a, b) pour a + b
+-- __sub(a, b) pour a - b
+-- __mul(a, b) pour a * b
+-- __div(a, b) pour a / b
+-- __mod(a, b) pour a % b
+-- __pow(a, b) pour a ^ b
+-- __unm(a) pour -a
+-- __concat(a, b) pour a .. b
+-- __len(a) pour #a
+-- __eq(a, b) pour a == b
+-- __lt(a, b) pour a < b
+-- __le(a, b) pour a <= b
+-- __index(a, b) <fn ou table> pour a.b
+-- __newindex(a, b, c) pour a.b = c
+-- __call(a, ...) pour a(...)
+
+----------------------------------------------------
+-- 3.2 Pseudo-orienté objet et héritage.
+----------------------------------------------------
+
+-- Lua n'implémente pas d'orienté objet par défaut.
+-- Mais il reste possible d'imiter de plusieurs manières
+-- le concept de "classe" grâce aux tables et aux métatables.
+
+-- L'explication pour l'exemple qui suit vient juste après.
+
+Dog = {} -- 1.
+
+function Dog:new() -- 2.
+ local newObj = {sound = 'woof'} -- 3.
+ self.__index = self -- 4.
+ return setmetatable(newObj, self) -- 5.
+end
+
+function Dog:makeSound() -- 6.
+ print('Je dis: ' .. self.sound..'!')
+end
+
+mrDog = Dog:new() -- 7.
+mrDog:makeSound() -- 'Je dis: woof! -- 8.
+
+-- 1. Dog agit comme une classe; c'est une simple table.
+-- 2. L'expression tbl:fn(...) est identique à
+-- tbl.fn(self, ...)
+-- La notation : permet de passer par défaut un premier
+-- argument appelé "self" à la fonction tbl.fn
+-- Voir 7 & 8 ci-après pour comprendre comment self prend
+-- sa valeur.
+-- 3. newObj sera une instance de la classe Dog.
+-- 4. self = la classe instanciée. Souvent, self = Dog, mais
+-- cela peut changer du fait de l'héritage.
+-- newObj reçoit les fonctions de self si l'__index des
+-- métatables de newObj et de self pointent vers self.
+-- 5. Rappel: setmetatable retourne son premier argument.
+-- 6. La notation : fonctionne comme au 2, mais cette fois, self
+-- est une instance au lieu d'être une classe.
+-- 7. Similaire à Dog.new(Dog), donc self = Dog dans new().
+-- 8. Similaire à mrDog.makeSound(mrDog); self = mrDog.
+
+----------------------------------------------------
+
+-- Exemple d'héritage:
+
+LoudDog = Dog:new() -- 1.
+
+function LoudDog:makeSound()
+ local s = self.sound .. ' ' -- 2.
+ print(s .. s .. s..'!')
+end
+
+seymour = LoudDog:new() -- 3.
+seymour:makeSound() -- 'woof woof woof!' -- 4.
+
+-- 1. LoudDog reçoit les méthodes et les variables de Dog.
+-- 2. self possède une clé 'sound', reçue de new(), voir 3.
+-- 3. Similaire à LoudDog.new(LoudDog) et traduit en Dog.new(LoudDog),
+-- puisque LoudDog ne possède pas de clé 'new', mais a une métatable
+-- qui a la clé __index = Dog.
+-- Résulat: la métatable de seymour est LoudDog, et
+-- LoudDog.__index = LoudDog. Donc seymour.key deviendra soit égal à
+-- seymour.key, LoudDog.key, Dog.key, selon le fait qu'il s'agira
+-- de la première table ayant la clé 'key' en question, en remontant
+-- dans la hiérarchie.
+-- 4. La clé 'makeSound' est trouvée dans LoudDog; cela est similaire
+-- à LoudDog.makeSound(seymour).
+
+-- Si besoin est, la méthode new() de la sous-classe est
+-- identique à la méthode new() de sa classe mère:
+function LoudDog:new()
+ local newObj = {}
+ -- Prépare self à être la superclasse de newObj:
+ self.__index = self
+ return setmetatable(newObj, self)
+end
+
+----------------------------------------------------
+-- 4. Modules.
+----------------------------------------------------
+
+
+--[[ Cette section est mise en commentaire afin que le reste du
+-- ce script reste exécutable.
+```
+
+```lua
+-- Supposons que le fichier mod.lua contienne ceci:
+local M = {}
+
+local function sayMyName()
+ print('Hrunkner')
+end
+
+function M.sayHello()
+ print('hello')
+ sayMyName()
+end
+
+return M
+
+-- Un autre fichier peut exploiter le contenu défini dans mod.lua's:
+local mod = require('mod') -- Exécute le fichier mod.lua.
+
+-- require est le moyen par défaut d'inclure des modules.
+-- require agit comme: (si non trouvé en cache; voir ci-après)
+local mod = (function ()
+ <contenu de mod.lua>
+end)()
+-- Comme si le contenu de mod.lua était enveloppé dans le corps d'une fonction,
+-- si bien que les variables locales contenues dans mod.lua sont
+-- inaccessibles en dehors de ce module.
+
+-- Le code suivant fonctionne car mod = M (dans mod.lua):
+mod.sayHello() -- Dis bonjour à Hrunkner.
+
+-- Le code suivant génère une erreur car sayMyName est local à mod.lua:
+mod.sayMyName() -- erreur!
+
+-- Les valeurs retournées par require sont mises en cache, ce qui fait
+-- qu'un module est toujours chargé une seule fois, même s'il est inclus
+-- avec require à plusieurs reprises.
+
+-- Supposons que mod2.lua contienne le code "print('Hi!')".
+local a = require('mod2') -- Affiche "Hi!"
+local b = require('mod2') -- N'affiche rien; et a = b.
+
+-- dofile est identique à require, sauf qu'il ne fait pas de mise en cache:
+dofile('mod2') --> Hi!
+dofile('mod2') --> Hi! (le code de mod2.lua est encore exécuté)
+
+-- loadfile charge le contenu d'un fichier, sans l'exécuter.
+f = loadfile('mod2') -- L'appel f() exécute le contenu de mod2.lua.
+
+-- loadstring est similaire à loadfile, mais pour les chaines de caractères.
+g = loadstring('print(343)') -- Retourne une fonction.
+g() -- Affiche 343; Rien n'est affiché avant cet appel.
+
+--]]
+
+```
+## Références
+
+*Les références qui suivent sont en Anglais.*
+
+Les sujets non abordés dans ce tutoriel sont couverts en intégralité par
+les librairies standard:
+
+* La librairie <a href="http://lua-users.org/wiki/StringLibraryTutorial">string</a>
+* La librairie <a href="http://lua-users.org/wiki/TableLibraryTutorial">table</a>
+* La librairie <a href="http://lua-users.org/wiki/MathLibraryTutorial">math</a>
+* La librairie <a href="http://lua-users.org/wiki/IoLibraryTutorial">io</a>
+* La librairie <a href="http://lua-users.org/wiki/OsLibraryTutorial">os</a>
+
+Autres références complémentaires:
+
+* <a href="http://nova-fusion.com/2012/08/27/lua-for-programmers-part-1/">Lua for programmers</a>
+* <a href="lua-users.org/files/wiki_insecure/users/thomasl/luarefv51.pdf">Courte de référence de Lua</a>
+* <a href="http://www.lua.org/pil/contents.html">Programming In Lua</a>
+* <a href="http://www.lua.org/manual/">Les manuels de référence Lua</a>
+
+A propos, ce fichier est exécutable. Sauvegardez-le sous le nom *learn.lua* et
+exécutez-le avec la commande `lua learn.lua` !
+
+Ce tutoriel a été originalement écrit pour <a href="tylerneylon.com">tylerneylon.com</a> et est aussi
+disponible en tant que <a href="https://gist.github.com/tylerneylon/5853042">gist</a>.
+Il a été traduit en français par Roland Yonaba (voir son <a href="http://github.com/Yonaba">github</a>).
+
+Amusez-vous bien avec Lua! \ No newline at end of file
diff --git a/fr-fr/objective-c-fr.html.markdown b/fr-fr/objective-c-fr.html.markdown
new file mode 100644
index 00000000..b98d161e
--- /dev/null
+++ b/fr-fr/objective-c-fr.html.markdown
@@ -0,0 +1,528 @@
+---
+
+language: Objective-C
+contributors:
+ - ["Eugene Yagrushkin", "www.about.me/yagrushkin"]
+ - ["Yannick Loriot", "https://github.com/YannickL"]
+ - ["Levi Bostian", "https://github.com/levibostian"]
+translators:
+ - ["Yannick Loriot", "https://github.com/YannickL"]
+filename: LearnObjectiveC-fr.m
+lang: fr-fr
+
+---
+
+L'Objective-C est un langage de programmation orienté objet réflexif principalement utilisé par Apple pour les systèmes d'exploitations Mac OS X et iOS et leurs frameworks respectifs, Cocoa et Cocoa Touch.
+
+```cpp
+// Les commentaires sur une seule ligne commencent par //
+
+/*
+Les
+commentaires
+multi-lignes
+ressemblent
+ceci
+*/
+
+// #import permet d'importer les en-têtes d'autres fichiers
+// Utilisez <> pour importer des fichiers globaux (en général des frameworks)
+// Utilisez "" pour importer des fichiers locaux (du projet)
+#import <Foundation/Foundation.h>
+#import "MaClasse.h"
+
+// Si vous activez les modules dans les projets iOS >= 7 ou Mac OS X >= 10.9
+// dans Xcode 5, vous pouvez importer les frameworks comme cela :
+@import Foundation;
+
+// Le point d'entrée de votre programme est une fonction qui s'appelle main
+// et qui retourne un entier comme type
+int main (int argc, const char * argv[])
+{
+ // Créer un groupe de libération automatique de la mémoire pour l'ensemble
+ // du programme
+ NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
+ // Si vous utilisez le comptage de référence automatique (ARC), utilisez
+ // @autoreleasepool à la place :
+ @autoreleasepool {
+
+ // NSLog() permet d'afficher une chaine de caractères dans la console
+ // Affiche la chaine de caractères "Bonjour Tous Le Monde !"
+ NSLog(@"Bonjour tous le Monde !");
+
+ ///////////////////////////////////////
+ // Les Types & Les Variables
+ ///////////////////////////////////////
+
+ // La déclaration de primitive
+ int maPrimitive1 = 1;
+ long maPrimitive2 = 234554664565;
+
+ // La déclaration d'objet
+ // Il faut mettre un astérisque devant la déclaration d'objet fortement typé
+ MaClasse *monObject1 = nil; // Typage fort
+ id monObject2 = nil; // Typage faible
+ // 'description' est une méthode qui permet de retourner un aperçut de l'objet sous forme textuelle
+ // La méthode 'description' est appelée par défaut quand on utilise le paramètre '%@'
+ NSLog(@"%@ and %@", monObject1, [monObject2 description]); // Affiche "(null) et (null)"
+
+ // Les chaines de caractères
+ NSString *chaineMonde = @"Monde";
+ NSLog(@"Bonjour tous le %@ !", chaineMonde); // affiche => "Bonjour Tous Le Monde !"
+ // NSMutableString est une chaine mutable
+ NSMutableString *chaineMutable = [NSMutableString stringWithString:@"Bonjour tous le"];
+ [chaineMutable appendString:@" Monde !"];
+ NSLog(@"%@", chaineMutable); // affiche => "Bonjour Tous Le Monde !"
+
+ // Les caractères
+ NSNumber *laLettreZSousFormeDeNombre = @'Z';
+ char laLettreZ = [laLettreZSousFormeDeNombre charValue]; // ou 'Z'
+ NSLog(@"%c", laLettreZ);
+
+ // Les nombres
+ NSNumber *nombreQuaranteDeux = @42;
+ int quaranteDeux = [nombreQuaranteDeux intValue]; // ou 42
+ NSLog(@"%i", quaranteDeux);
+
+ NSNumber *nombreQuaranteDeuxnonSigne = @42U;
+ unsigned int quaranteDeuxnonSigne = [nombreQuaranteDeuxnonSigne unsignedIntValue];
+ NSLog(@"%u", fortyTwoUnsigned);
+
+ NSNumber *nombreQuaranteDeuxCourt = [NSNumber numberWithShort:42];
+ short quaranteDeuxCourt = [nombreQuaranteDeuxCourt shortValue]; // ou 42
+ NSLog(@"%hi", fortyTwoShort);
+
+ NSNumber *nombreQuaranteDeuxLong = @42L;
+ long quaranteDeuxLong = [nombreQuaranteDeuxLong longValue]; // ou 42
+ NSLog(@"%li", fortyTwoLong);
+
+ // Les nombres flottants
+ NSNumber *nombrePiFlottant = @3.141592654F;
+ float piFlottant = [nombrePiFlottant floatValue]; // ou 3.141592654f
+ NSLog(@"%f", piFlottant); // affiche => 3.141592654
+ NSLog(@"%5.2f", piFlottant); // affiche => " 3.14"
+
+ NSNumber *nombrePiDouble = @3.1415926535;
+ double piDouble = [nombrePiDouble doubleValue]; // ou 3.1415926535
+ NSLog(@"%f", piDouble);
+ NSLog(@"%4.2f", piDouble); // affiche => "3.14"
+
+ // NSDecimalNumber est une classe pour avoir plus de précision sur les nombres
+ // flottants et les doubles
+ NSDecimalNumber *decNumUn = [NSDecimalNumber decimalNumberWithString:@"10.99"];
+ NSDecimalNumber *decNumDeux = [NSDecimalNumber decimalNumberWithString:@"5.002"];
+ // NSDecimalNumber ne permet pas d'utiliser les opérations standards (+, -, *, /)
+ // Il faut utiliser les méthodes suivantes à la place :
+ [decNumUn decimalNumberByAdding:decNumDeux];
+ [decNumUn decimalNumberBySubtracting:decNumDeux];
+ [decNumUn decimalNumberByMultiplyingBy:decNumDeux];
+ [decNumUn decimalNumberByDividingBy:decNumDeux];
+ NSLog(@"%@", decNumUn); // affiche => 10.99 comme NSDecimalNumber est immuable
+
+ // Les booléens
+ NSNumber *ouiNumber = @YES;
+ NSNumber *nonNumber = @NO;
+ // ou
+ BOOL ouiBool = YES;
+ BOOL nonBool = NO;
+ NSLog(@"%i", ouiBool); // affiche => 1
+
+ // Les listes
+ // Une liste peut contenir uniquement des objets
+ NSArray *uneListe = @[@1, @2, @3, @4];
+ NSNumber *troisiemeNombre = uneListe[2];
+ NSLog(@"Troisième nombre = %@", troisiemeNombre); // affiche "Troisième nombre = 3"
+ // NSMutableArray est une version mutable de NSArray
+ // Cela permet de modifier la liste en ajoutant de nouveaux éléments et en supprimant ou
+ // changeant de place des objets déjà présent
+ // C'est très pratique, mais pas aussi performant que l'utilisation de la classe NSArray
+ NSMutableArray *listeMutable = [NSMutableArray arrayWithCapacity:2];
+ [listeMutable addObject:@"Bonjour tous le"];
+ [listeMutable addObject:@"Monde"];
+ [listeMutable removeObjectAtIndex:0];
+ NSLog(@"%@", [listeMutable objectAtIndex:0]); // affiche => "Monde"
+
+ // Les dictionnaires
+ // Un dictionnaire est un ensemble de clés : valeurs
+ NSDictionary *unDictionnaire = @{ @"cle1" : @"valeur1", @"cle2" : @"valeur2" };
+ NSObject *valeur = unDictionnaire[@"Une clé"];
+ NSLog(@"Objet = %@", valeur); // affiche "Objet = (null)"
+ // NSMutableDictionary est un dictionnaire mutable, c-à-d que l'on peut modifier
+ NSMutableDictionary *dictionnaireMutable = [NSMutableDictionary dictionaryWithCapacity:2];
+ [dictionnaireMutable setObject:@"valeur1" forKey:@"cle1"];
+ [dictionnaireMutable setObject:@"valeur2" forKey:@"cle2"];
+ [dictionnaireMutable removeObjectForKey:@"cle1"];
+
+ // Les ensembles
+ // Un ensemble ne peut contenir de duplicatas contrairement aux NSArray
+ NSSet *ensemble = [NSSet setWithObjects:@"Salut", @"Salut", @"Monde", nil];
+ NSLog(@"%@", ensemble); // affiche => {(Salut, Monde)} (Pas forcément dans le même ordre)
+ // NSMutableSet est un ensemble mutable
+ NSMutableSet *ensembleMutable = [NSMutableSet setWithCapacity:2];
+ [ensembleMutable addObject:@"Salut"];
+ [ensembleMutable addObject:@"Salut"];
+ NSLog(@"%@", ensembleMutable); // affiche => {(Salut)}
+
+ ///////////////////////////////////////
+ // Les Operateurs
+ ///////////////////////////////////////
+
+ // Les opérateurs sont pareil qu'en C
+ // Par exemple :
+ 2 + 5; // => 7
+ 4.2f + 5.1f; // => 9.3f
+ 3 == 2; // => 0 (NO)
+ 3 != 2; // => 1 (YES)
+ 1 && 1; // => 1 (et logique)
+ 0 || 1; // => 1 (ou logique)
+ ~0x0F; // => 0xF0 (négation bit à bit)
+ 0x0F & 0xF0; // => 0x00 (et bit à bit)
+ 0x01 << 1; // => 0x02 (décalage à gauche (par 1))
+
+ ///////////////////////////////////////
+ // Les Structures de Contrôle
+ ///////////////////////////////////////
+
+ // Structure "Si-Sinon" (If-Else)
+ if (NO)
+ {
+ NSLog(@"Je ne suis jamais affiché");
+ } else if (0)
+ {
+ NSLog(@"Je ne suis jamais affiché aussi");
+ } else
+ {
+ NSLog(@"Je suis affiché");
+ }
+
+ // Structure "Selon" (Switch)
+ switch (2)
+ {
+ case 0:
+ {
+ NSLog(@"Je ne suis jamais affiché");
+ } break;
+ case 1:
+ {
+ NSLog(@"Je ne suis jamais affiché aussi");
+ } break;
+ default:
+ {
+ NSLog(@"Je suis affiché");
+ } break;
+ }
+
+ // Structure de boucle "Tant Que" (While)
+ int ii = 0;
+ while (ii < 4)
+ {
+ NSLog(@"%d,", ii++); // ii++ incrémente ii après avoir utilisé sa valeur
+ } // => affiche "0,"
+ // "1,"
+ // "2,"
+ // "3,"
+
+ // Structure de boucle "Pour" (For)
+ int jj;
+ for (jj=0; jj < 4; jj++)
+ {
+ NSLog(@"%d,", jj);
+ } // => affiche "0,"
+ // "1,"
+ // "2,"
+ // "3,"
+
+ // Structure de boucle "Pour Chaque" (Foreach)
+ NSArray *valeurs = @[@0, @1, @2, @3];
+ for (NSNumber *valeur in valeurs)
+ {
+ NSLog(@"%@,", valeur);
+ } // => affiche "0,"
+ // "1,"
+ // "2,"
+ // "3,"
+
+ // Structure "Essayer-Attraper-Finalement" (Try-Catch-Finally)
+ @try
+ {
+ @throw [NSException exceptionWithName:@"FileNotFoundException"
+ reason:@"Fichier non trouvé" userInfo:nil];
+ } @catch (NSException * e)
+ {
+ NSLog(@"Une exception est survenue : %@", e);
+ } @finally
+ {
+ NSLog(@"Finalement");
+ } // => affiche "Une exception est survenue : Fichier non trouvé"
+ // "Finalement"
+
+ ///////////////////////////////////////
+ // Les Objets
+ ///////////////////////////////////////
+
+ // Définis et créé une instance d'objet en allouant un espace mémoire puis en
+ // l'initialisant. Un objet n'est pas complétement fonctionnel tant que les deux
+ // étapes précédentes ne sont pas terminées
+ MaClass *monObjet = [[MaClass alloc] init];
+
+ // L'Objet en Objective-C est basé sur le principe d'envoie de message et non sur
+ // celui d'appel de méthode comme la plupart des autres langages
+ // C'est un détail important car cela veut dire que l'on peut envoyer un message
+ // à un objet qui ne possède pas la méthode demandée sans aucune incidence sur le
+ // fonctionnement du programme (aucune exception ne sera levée)
+ [myObject instanceMethodWithParameter:@"Steve Jobs"];
+
+ // Nettoie la mémoire qui a été utilisée dans le programme
+ [pool drain];
+
+ // Fin de l'@autoreleasepool
+ }
+
+ // Fin du programme
+ return 0;
+}
+
+///////////////////////////////////////
+// Les Classes et Les Fonctions
+///////////////////////////////////////
+
+// Déclaration d'une classe dans un en-tête de fichier (MaClasse.h) :
+// La déclaration d'une classe en Objective-C commence par la déclaration de son interface :
+// @interface NomDeLaClasse : NomDeLaClasseParent <ListeDesProtocoles>
+// {
+// type nom; // Déclaration d'une variable;
+// }
+// @property type nom; // Déclaration d'une propriété
+// -/+ (type)nomDeLaMethode; // Déclaration d'une methode
+// @end // Termine la déclaration
+// NSObject est la classe de base (super classe) en Objective-C
+@interface MaClasse : NSObject <MonProtocole>
+{
+ int nombre; // Accès protégé par défaut (équivalent à '@protected int nombre;')
+ @private id donnee; // Accès privé (il est plus pratique de le faire dans l'implémentation)
+ NSString *nom;
+}
+// Les propriétés permettent de générer les accésseurs/affecteurs publiques à la compilation
+// Par défaut, le nom de l'affecteur est la chaine 'set' suivi par le nom de la @property
+@property int propInt; // Nom de l'affecteur = 'setPropInt'
+@property (copy) id copyId; // (copy) => Copie l'objet pendant l'affectation
+// (readonly) => Ne peut pas affecté la variable en dehors de l'@interface
+// Il faut utiliser le mot clé '@synthesize' dans l'@implementation pour créer l'accésseur
+@property (readonly) NSString *roString;
+// Vous pouvez aussi personnaliser les noms des accésseurs ou des affecteurs
+@property (getter=longeurGet, setter=longeurSet:) int longeur;
+
+// Methodes
++/- (TypeDeRetour)signatureDeLaMethode:(TypeDuParametre *)nomDuParametre;
+
+// '+' signifie que c'est une méthode de classe (statique) :
++ (NSString *)methodeDeClasse;
++ (MaClasse *)maClasseDepuisLaHauteur:(NSNumber *)hauteurParDefaut;
+
+// '-' pour les méthodes d'instances :
+- (NSString *)methodeInstanceAvecUnParametre:(NSString *)string;
+- (NSNumber *)methodeInstanceAvecUnParametre:(NSString*)string puisUnDeuxieme:(NSNumber *)number;
+
+// Contructeur avec des arguments :
+- (id)initAvecDistance:(int)distanceParDefault;
+// Les méthodes en Objective-C sont très descriptives
+
+@end // Fin de l'interface
+
+
+// Voici un exemple d'utilisation de MaClasse
+MaClasse *maClasse = [[MaClasse alloc] init]; // créer une instance de MaClasse
+[maClasse setNombre:10];
+NSLog(@"%d", [maClasse nombre]); // affiche => 10
+[myClass longeurSet:32];
+NSLog(@"%i", [maClasse longeurGet]); // affiche => 32
+// Pour des raisons pratiques vous pouvez aussi utiliser la notation en point pour accéder aux
+// variables d'instances :
+maClasse.nombre = 45;
+NSLog(@"%i", maClasse.nombre); // maClasse => 45
+
+// Pour appeler une méthode de classe :
+NSString *s1 = [MaClasse methodeDeClasse];
+MaClasse *m2 = [MaClasse maClasseDepuisLaHauteur:38];
+
+// Pour appeler une méthode d'instance :
+MaClasse *maClasse = [[MaClasse alloc] init]; // Créer une instance de MaClasse
+NSString *stringDepuisUneInstanceDeMethode = [maClasse methodeInstanceAvecUnParametre:@"Salut"];
+
+// Les sélecteurs sont un moyen de décrire les méthodes dynamiquement
+// Ils sont utilisés pour appeler des méthodes de classe et avoir des pointeurs de fonctions
+// facilement manipulable
+// SEL est un type de donnée et @selector retourne un selecteur à partir d'un nom de methode
+SEL selecteur = @selector(methodeInstanceAvecUnParametre:puisUnDeuxieme:);
+if ([maClasse respondsToSelector:selecteur]) { // Vérifie si la classe possède la méthode
+ // Met les arguments de la méthode dans un seul objet pour l'envoyer via la fonction
+ // performSelector:withObject:
+ NSArray *arguments = [NSArray arrayWithObjects:@"Hello", @4, nil];
+ [myClass performSelector:selectorVar withObject:arguments]; // Appele la méthode via le sélecteur
+}
+else {
+ // NSStringFromSelector() retourne une chaine de caractères à partir d'un sélecteur
+ NSLog(@"MaClasse ne possède pas de méthode : %@", NSStringFromSelector(selecteur));
+}
+
+// Le fichier d'implémentation de la classe MaClasse (MaClasse.m) doit commencer comme ceci :
+@implementation MaClasse {
+ long distance; // Variable d'instance privée (équivalent à @private dans l'interface)
+ NSNumber hauteur;
+}
+
+// Pour accéder à une variable depuis l'implémentation on peut utiliser le _ (tiret bas) devant le nom
+// de la variable :
+_nombre = 5;
+// Accès d'une variable définie dans le fichier d'implémentation :
+distance = 18;
+// Pour utiliser la variable définie par l'intermédiaire de @property, il faut utiliser @synthesize
+// qui permet de créer les affecteurs et les accésseurs correspondants :
+@synthesize roString = _roString; // _roString est maintenant disponible dans l'implementation
+
+// A l'inverse dela méthode 'init' qui est appelée lors de la création d'un objet, la fonction
+// 'dealloc' est appelée quand l'objet est supprimé
+- (void)dealloc
+{
+ [hauteur release]; // Si vous n'utilisez pas ARC, pensez bien à supprimer l'objet
+ [super dealloc]; // et à appeler la méthode 'dealloc' de la classe parent
+}
+
+// Les constructeurs sont des fonctions qui permettent d'instancier un objet
+// 'init' est le constructeur par défaut en Objective-C
+- (id)init
+{
+ if ((self = [super init])) // 'super' est utilisé pour appeler la méthode de la classe parent
+ {
+ self.count = 1; // 'self' permet d'appeler la méthode de l'instance courante
+ }
+ return self;
+}
+
+// Vous pouvez aussi créer des constructeurs avec des arguments
+// Attention : chaque nom de constructeur doit absolument commencer par 'init'
+- (id)initAvecUneDistance:(int)distanceParDefault
+{
+ if ((self = [super init]))
+ {
+ distance = distanceParDefault;
+ return self;
+ }
+}
+
+// Implémentation d'une méthode de classe
++ (NSString *)methodDeClasse
+{
+ return [[self alloc] init];
+}
+
++ (MaClasse *)maClasseDepuisUneHauteur:(NSNumber *)hauteurParDefaut
+{
+ hauteur = hauteurParDefaut;
+ return [[self alloc] init];
+}
+
+// Implémentation d'une méthode d'instance
+- (NSString *)methodeInstanceAvecUnParametre:(NSString *)string
+{
+ return @"Ma chaine de caractère";
+}
+
+- (NSNumber *)methodeInstanceAvecUnParametre:(NSString*)string puisUnDeuxieme:(NSNumber *)number
+{
+ return @42;
+}
+
+// Pour créer une méthode privée, il faut la définir dans l'implementation et non pas dans
+// l'interface
+- (NSNumber *)methodePrivee
+{
+ return @72;
+}
+
+[self methodePrivee]; // Appel de la méthode privée
+
+// Implémentation d'une méthode qui est déclarée dans <MonProtocole>
+- (void)methodeDuProtocole
+{
+ // expressions
+}
+
+@end // Fin de l'implémentation
+
+/*
+ * Un protocole déclare des méthodes et propriétés que chaque implémentation doit avoir afin de se
+ * conformer à celui-ci
+ * Un protocole n'est pas une classe, c'est juste une interface
+ */
+@protocol MonProtocole
+ - (void)methodeDuProtocole;
+@end
+
+
+///////////////////////////////////////
+// Gestion de la mémoire
+///////////////////////////////////////
+/*
+À chaque fois qu'un objet est créé dans l'application, un bloc mémoire doit être alloué.
+Quand l'application en a fini avec cet objet, la mémoire doit être libérée afin d'éviter les fuites
+mémoires
+Il n'y a pas de ramasse-miettes en Objective-C contrairement à Java par exemple. La gestion de la
+mémoire repose sur le comptage de référence qui, pour chaque objet, assigne un compteur qui permet
+de connaitre le nombre de référence qui l'utilise.
+
+Le principe est le suivant :
+Lorsque l'objet est créé, le compteur est initialisé à 1. Quand une instance détient un objet, le
+compteur est incrémenté de un. Quand l'objet est libéré, le compteur est décrémenté de un. Au moment
+où le compteur arrive à zéro, l'objet est supprimé de la mémoire
+
+Une bonne pratique à suivre quand on travaille avec des objets est la suivante :
+(1) créer un objet, (2) utiliser l'objet, (3) supprimer l'objet de la mémoire
+*/
+
+MaClasse *classeVar = [MyClass alloc]; // 'alloc' incrémente le compteur de référence
+[classeVar release]; // Décrémente le compteur de rérence
+// 'retain' incrémente le compteur de référence
+// Si 'classeVar' est libéré, l'objet reste en mémoire car le compteur de référence est non nul
+MaClasse *nouvelleVar = [classVar retain];
+[classeVar autorelease]; // Supprime l'appartenance de l'objet à la fin du bloc
+
+// Les @property peuvent utiliser 'retain' et 'assign'
+@property (retain) MaClasse *instance; // Libère l'ancienne valeur et retient la nouvelle
+@property (assign) NSSet *set; // Pointeur vers la valeur sans retenir/libérer l'ancienne valeur
+
+// Automatic Reference Counting (ARC)
+// La gestion de la mémoire étant pénible, depuis iOS 4 et Xcode 4.2, Apple a introduit le comptage de
+// référence automatique (Automatic Reference Counting en anglais)
+// ARC est une fonctionnalité du compilateur qui permet d'ajouter les 'retain', 'release' et 'autorelease'
+// automatiquement. Cela veut dire que lorsque vous utilisez ARC vous ne devez plus utiliser ces mot-clés
+MaClasse *arcMaClasse = [[MaClasse alloc] init];
+// ... code utilisant arcMaClasse
+// Sans ARC, vous auriez dû appeler [arcMaClasse release] après avoir utilisé l'objet. Mais avec ARC
+// activé il n'est plus nécessaire de le faire car le compilateur ajoutera l'expréssion automatiquement
+// pour vous
+
+// Les mots clés 'assign' et 'retain', avec ARC sont respectivement remplacé par 'weak' et 'strong'
+@property (weak) MaClasse *weakVar; // 'weak' ne retient pas l'objet. Si le compteur de référence
+// descend à zero, weakVar sera automatiquement mis à nil
+@property (strong) MaClasse *strongVar; // 'strong' prend possession de l'objet comme le ferait avec
+// le mot-clé 'retain'
+
+// Pour l'instanciation des variables (en dehors de @property), vous pouvez utiliser les instructions
+// suivantes :
+__strong NSString *strongString; // Par défaut. La variable est retenue en mémoire jusqu'à la fin
+// de sa portée
+__weak NSSet *weakSet; // Maintient une référence vers l'objet sans incrémenter son compteur de référence :
+// Lorsque l'objet sera supprimé, weakSet sera mis à nil automatiquement
+__unsafe_unretained NSArray *unsafeArray; // Comme __weak, mais la variable n'est pas mis à nil quand
+// l'objet est supprimé
+
+```
+## Lectures Complémentaires
+
+[La Page Wikipedia de l'Objective-C](http://fr.wikipedia.org/wiki/Objective-C)
+
+[iOS pour les écoliers : Votre première app iOS](http://www.raywenderlich.com/fr/39272/ios-pour-les-ecoliers-votre-premiere-app-ios-partie-12)
+
+[Programming with Objective-C. Apple PDF book](https://developer.apple.com/library/ios/documentation/cocoa/conceptual/ProgrammingWithObjectiveC/ProgrammingWithObjectiveC.pdf)
diff --git a/fr-fr/python-fr.html.markdown b/fr-fr/python-fr.html.markdown
new file mode 100644
index 00000000..58a036ba
--- /dev/null
+++ b/fr-fr/python-fr.html.markdown
@@ -0,0 +1,489 @@
+---
+language: python
+filename: learnpython-fr.py
+contributors:
+ - ["Louie Dinh", "http://ldinh.ca"]
+translators:
+ - ["Sylvain Zyssman", "https://github.com/sylzys"]
+ - ["Nami-Doc", "https://github.com/Nami-Doc"]
+lang: fr-fr
+---
+
+Python a été créé par Guido Van Rossum au début des années 90. C'est maintenant un des langages de programmation les plus populaires.
+Je suis tombé amoureux de Python de par la clarté de sa syntaxe. C'est pratiquement du pseudo-code exécutable.
+
+Vos retours sont grandement appréciés. Vous pouvez me contacter sur Twitter [@louiedinh](http://twitter.com/louiedinh) ou par e-mail: louiedinh [at] [google's email service]
+
+NB: Cet artice s'applique spécifiquement à Python 2.7, mais devrait s'appliquer pour toute version Python 2.x
+Vous pourrez bientôt trouver un article pour Python 3!
+
+```python
+# Une ligne simple de commentaire commence par un dièse
+""" Les lignes de commenatires multipes peuvent être écrites
+ en utilisant 3 guillemets ("), et sont souvent utilisées
+ pour les commentaires
+"""
+
+####################################################
+## 1. Types Primaires et Opérateurs
+####################################################
+
+# Les nombres
+3 #=> 3
+
+# Les calculs produisent les résultats mathématiques escomptés
+1 + 1 #=> 2
+8 - 1 #=> 7
+10 * 2 #=> 20
+35 / 5 #=> 7
+
+# La division est un peu spéciale. C'est une division d'entiers, et Python arrondi le résultat par défaut automatiquement.
+5 / 2 #=> 2
+
+# Pour corriger ce problème, on utilise les float.
+2.0 # Voici un float
+11.0 / 4.0 #=> 2.75 ahhh... beaucoup mieux
+
+# Forcer la priorité avec les parenthèses
+(1 + 3) * 2 #=> 8
+
+# Les valeurs booléenes sont de type primitif
+True
+False
+
+# Pour la négation, on utilise "not"
+not True #=> False
+not False #=> True
+
+# Pour l'égalité, ==
+1 == 1 #=> True
+2 == 1 #=> False
+
+# L'inégalité est symbolisée par !=
+1 != 1 #=> False
+2 != 1 #=> True
+
+# D'autres comparateurs
+1 < 10 #=> True
+1 > 10 #=> False
+2 <= 2 #=> True
+2 >= 2 #=> True
+
+# On peut enchaîner les comparateurs !
+1 < 2 < 3 #=> True
+2 < 3 < 2 #=> False
+
+# Les chaînes de caractères sont créées avec " ou '
+"C'est une chaîne."
+'C\'est aussi une chaîne.'
+
+# On peut aussi les "additioner" !
+"Hello " + "world!" #=> "Hello world!"
+
+# Une chaîne peut être traitée comme une liste de caractères
+"C'est une chaîne"[0] #=> 'C'
+
+# % peut être utilisé pour formatter des chaîne, comme ceci:
+"%s can be %s" % ("strings", "interpolated")
+
+# Une autre manière de formatter les chaînes de caractères est d'utiliser la méthode 'format'
+# C'est la méthode à privilégier
+"{0} peut être {1}".format("La chaîne", "formattée")
+# On peut utiliser des mot-clés au lieu des chiffres.
+"{name} veut manger des {food}".format(name="Bob", food="lasagnes")
+
+# None est un objet
+None #=> None
+
+# Ne pas utiliser le symbole d'inégalité "==" pour comparer des objet à None
+# Il faut utiliser "is"
+"etc" is None #=> False
+None is None #=> True
+
+# L'opérateur 'is' teste l'identité de l'objet.
+# Ce n'est pas très utilisé avec les types primitifs, mais cela peut être très utile
+# lorsque l'on utilise des objets.
+
+# None, 0, et les chaînes de caractères vides valent False.
+# Toutes les autres valeurs valent True
+0 == False #=> True
+"" == False #=> True
+
+
+####################################################
+## 2. Variables et Collections
+####################################################
+
+# Afficher du texte, c'est facile
+print "Je suis Python. Enchanté!"
+
+
+# Il n'y a pas besoin de déclarer les variables avant de les assigner.
+some_var = 5 # La convention veut que l'on utilise des minuscules_avec_underscores
+some_var #=> 5
+
+# Accéder à une variable non assignée lève une exception
+# Voyez les structures de contrôle pour en apprendre plus sur la gestion des exceptions.
+some_other_var # Lève une exception
+
+# 'if' peut être utilisé comme expression
+"yahoo!" if 3 > 2 else 2 #=> "yahoo!"
+
+# Listes
+li = []
+# On peut remplir liste dès l'instanciation
+other_li = [4, 5, 6]
+
+# On ajoute des éléments avec 'append'
+li.append(1) #li contient [1]
+li.append(2) #li contient [1, 2]
+li.append(4) #li contient [1, 2, 4]
+li.append(3) #li contient [1, 2, 4, 3]
+
+# Et on les supprime avec 'pop'
+li.pop() #=> 3 et li contient [1, 2, 4]
+# Remettons-le dans la liste
+li.append(3) # li contient [1, 2, 4, 3] de nouveau.
+
+# On accède aux éléments d'une liste comme à ceux un tableau.
+li[0] #=> 1
+# Le dernier élément
+li[-1] #=> 3
+
+# Accèder aux indices hors limite lève une exception
+li[4] # Lève un 'IndexError'
+
+# On peut accèder à des rangs de valeurs avec la syntaxe "slice"
+# (C'est un rang de type 'fermé/ouvert' pour les plus matheux)
+li[1:3] #=> [2, 4]
+# Sans spécifier de fin de rang, on "saute" le début de la liste
+li[2:] #=> [4, 3]
+# Sans spécifier de début de rang, on "saute" la fin de la liste
+li[:3] #=> [1, 2, 4]
+
+# Retirer un élément spécifique dee la liste avec "del"
+del li[2] # li contient [1, 2, 3]
+
+# On peut additionner des listes entre elles
+li + other_li #=> [1, 2, 3, 4, 5, 6] - Note: li et other_li existent toujours à part entière
+
+# Concaténer des listes avec "extend()"
+li.extend(other_li) # li vaut maintenant [1, 2, 3, 4, 5, 6]
+
+# Vérifier l'existence d'un élément dans une liste avec "in"
+1 in li #=> True
+
+# Récupérer la longueur avec "len()"
+len(li) #=> 6
+
+
+# Les "tuples" sont comme des listes, mais sont immuables.
+tup = (1, 2, 3)
+tup[0] #=> 1
+tup[0] = 3 # Lève un 'TypeError'
+
+# Mais vous pouvez faire tout ceci sur les tuples:
+len(tup) #=> 3
+tup + (4, 5, 6) #=> (1, 2, 3, 4, 5, 6)
+tup[:2] #=> (1, 2)
+2 in tup #=> True
+
+# Vous pouvez "dé-packager" les tuples (ou les listes) dans des variables
+a, b, c = (1, 2, 3) # a vaut maintenant 1, b vaut maintenant 2 and c vaut maintenant 3
+# Sans parenthèses, un tuple est créé par défaut
+d, e, f = 4, 5, 6
+# Voyez maintenant comme il est facile d'inverser 2 valeurs
+e, d = d, e # d is now 5 and e is now 4
+
+
+# Dictionnaires
+empty_dict = {}
+# Un dictionnaire pré-rempli
+filled_dict = {"one": 1, "two": 2, "three": 3}
+
+# Trouver des valeurs avec []
+filled_dict["one"] #=> 1
+
+# Récupérer toutes les clés sous forme de liste avec "keys()"
+filled_dict.keys() #=> ["three", "two", "one"]
+# Note - l'ordre des clés du dictionnaire n'est pas garanti.
+# Vos résultats peuvent différer de ceux ci-dessus.
+
+# Récupérer toutes les valeurs sous forme de liste avec "values()"
+filled_dict.values() #=> [3, 2, 1]
+# Note - Même remarque qu'au-dessus concernant l'ordre des valeurs.
+
+# Vérifier l'existence d'une clé dans le dictionnaire avec "in"
+"one" in filled_dict #=> True
+1 in filled_dict #=> False
+
+# Chercher une clé non existante lève une 'KeyError'
+filled_dict["four"] # KeyError
+
+# Utiliser la méthode "get()" pour éviter 'KeyError'
+filled_dict.get("one") #=> 1
+filled_dict.get("four") #=> None
+# La méthode get() prend un argument par défaut quand la valeur est inexistante
+filled_dict.get("one", 4) #=> 1
+filled_dict.get("four", 4) #=> 4
+
+# La méthode "setdefault()" permet d'ajouter de manière sécuris une paire clé-valeur dans le dictionnnaire
+filled_dict.setdefault("five", 5) #filled_dict["five"] vaut 5
+filled_dict.setdefault("five", 6) #filled_dict["five"] is toujours 5
+
+
+# Les sets stockent ... des sets
+empty_set = set()
+# On initialise un "set()" avec tout un tas de valeurs
+some_set = set([1,2,2,3,4]) # some_set vaut maintenant set([1, 2, 3, 4])
+
+# Depuis Python 2.7, {} peut être utilisé pour déclarer un 'set'
+filled_set = {1, 2, 2, 3, 4} # => {1 2 3 4}
+
+# Ajouter plus d'éléments au set
+filled_set.add(5) # filled_set contient maintenant {1, 2, 3, 4, 5}
+
+# Intersection de sets avec &
+other_set = {3, 4, 5, 6}
+filled_set & other_set #=> {3, 4, 5}
+
+# Union de sets avec |
+filled_set | other_set #=> {1, 2, 3, 4, 5, 6}
+
+# Différence de sets avec -
+{1,2,3,4} - {2,3,5} #=> {1, 4}
+
+# Vérifier l'existence d'une valeur dans un set avec "in"
+2 in filled_set #=> True
+10 in filled_set #=> False
+
+
+####################################################
+## 3. Structure de contrôle
+####################################################
+
+# Initialisons une variable
+some_var = 5
+
+# Voici une condition 'if'. L'indentation est significative en Python !
+# Affiche "some_var est inférieur à 10"
+if some_var > 10:
+ print "some_var est supérieur à 10."
+elif some_var < 10: # La clause elif est optionnelle
+ print "some_var iinférieur à 10."
+else: # La clause else également
+ print "some_var vaut 10."
+
+
+"""
+Les boucles "for" permettent d'itérer sur les listes
+Affiche:
+ chien : mammifère
+ chat : mammifère
+ souris : mammifère
+"""
+for animal in ["chien", "chat", "souris"]:
+ # On peut utiliser % pour l'interpolation des chaînes formattées
+ print "%s : mammifère" % animal
+
+"""
+"range(number)" retourne une liste de nombres
+de 0 au nombre donné
+Affiche:
+ 0
+ 1
+ 2
+ 3
+"""
+for i in range(4):
+ print i
+
+"""
+Les boucles "while" boucle jusqu'à ce que leur condition ne soit plus vraie
+Affiche:
+ 0
+ 1
+ 2
+ 3
+"""
+x = 0
+while x < 4:
+ print x
+ x += 1 # Raccourci pour x = x + 1
+
+# Gérer les exceptions avec un bloc try/except
+
+# Fonctionne pour Python 2.6 et ultérieur:
+try:
+ # Utiliser "raise" pour lever une exception
+ raise IndexError("This is an index error")
+except IndexError as e:
+ pass # Pass ne prend pas d'arguments. Généralement, on gère l'erreur ici.
+
+
+####################################################
+## 4. Fonctions
+####################################################
+
+# Utiliser "def" pour créer une nouvelle fonction
+def add(x, y):
+ print "x vaut %s et y vaur %s" % (x, y)
+ return x + y # Renvoi de valeur avec 'return'
+
+# Appeller une fonction avec des paramètres
+add(5, 6) #=> Affichet "x is 5 et y vaut 6" et renvoie 11
+
+# Une autre manière d'appeller une fonction, avec les arguments
+add(y=6, x=5) # Les arguments peuvent venir dans n'importe quel ordre.
+
+# On peut définir une foncion qui prend un nombre variable de paramètres
+def varargs(*args):
+ return args
+
+varargs(1, 2, 3) #=> (1,2,3)
+
+
+# On peut également définir une fonction qui prend un nombre
+# variable d'arguments
+def keyword_args(**kwargs):
+ return kwargs
+
+# Appelons-là et voyons ce qu'il se passe
+keyword_args(big="foot", loch="ness") #=> {"big": "foot", "loch": "ness"}
+
+# On peut faire les deux à la fois si on le souhaite
+def all_the_args(*args, **kwargs):
+ print args
+ print kwargs
+"""
+all_the_args(1, 2, a=3, b=4) affiche:
+ (1, 2)
+ {"a": 3, "b": 4}
+"""
+
+# En appellant les fonctions, on peut faire l'inverse des paramètres / arguments !
+# Utiliser * pour développer les paramètres, et ** pour développer les arguments
+params = (1, 2, 3, 4)
+args = {"a": 3, "b": 4}
+all_the_args(*args) # equivaut à foo(1, 2, 3, 4)
+all_the_args(**kwargs) # equivaut à foo(a=3, b=4)
+all_the_args(*args, **kwargs) # equivaut à foo(1, 2, 3, 4, a=3, b=4)
+
+# Python a des fonctions de première classe
+def create_adder(x):
+ def adder(y):
+ return x + y
+ return adder
+
+add_10 = create_adder(10)
+add_10(3) #=> 13
+
+# Mais également des fonctions anonymes
+(lambda x: x > 2)(3) #=> True
+
+# On trouve aussi des fonctions intégrées plus évoluées
+map(add_10, [1,2,3]) #=> [11, 12, 13]
+filter(lambda x: x > 5, [3, 4, 5, 6, 7]) #=> [6, 7]
+
+# On peut utiliser la syntaxe des liste pour construire les "maps" et les "filters"
+[add_10(i) for i in [1, 2, 3]] #=> [11, 12, 13]
+[x for x in [3, 4, 5, 6, 7] if x > 5] #=> [6, 7]
+
+####################################################
+## 5. Classes
+####################################################
+
+# Une classe est un objet
+class Human(object):
+
+ # Un attribut de classe. Il est partagé par toutes les instances de cette classe.
+ species = "H. sapiens"
+
+ # Initialiseur basique
+ def __init__(self, name):
+ # Assigne le paramètre à l'attribut de l'instance de classe.
+ self.name = name
+
+ # Une méthode de l'instance. Toutes les méthodes prennent "self" comme 1er paramètre.
+ def say(self, msg):
+ return "%s: %s" % (self.name, msg)
+
+ # Une méthode de classe est partagée par toutes les instances.
+ # On les appelle avec le nom de la classe en premier paramètre
+ @classmethod
+ def get_species(cls):
+ return cls.species
+
+ # Une méthode statique est appellée sans référence à une classe ou à une instance
+ @staticmethod
+ def grunt():
+ return "*grunt*"
+
+
+# Instancier une classe
+i = Human(name="Ian")
+print i.say("hi") # Affiche "Ian: hi"
+
+j = Human("Joel")
+print j.say("hello") #Affiche "Joel: hello"
+
+# Appeller notre méthode de classe
+i.get_species() #=> "H. sapiens"
+
+# Changer les attributs partagés
+Human.species = "H. neanderthalensis"
+i.get_species() #=> "H. neanderthalensis"
+j.get_species() #=> "H. neanderthalensis"
+
+# Appeller la méthode statique
+Human.grunt() #=> "*grunt*"
+
+
+####################################################
+## 6. Modules
+####################################################
+
+# On peut importer des modules
+import math
+print math.sqrt(16) #=> 4
+
+# Et récupérer des fonctions spécifiques d'un module
+from math import ceil, floor
+print ceil(3.7) #=> 4.0
+print floor(3.7) #=> 3.0
+
+# Récuperer toutes les fonctions d'un module
+# Attention, ce n'est pas recommandé.
+from math import *
+
+# On peut raccourcir le nom d'un module
+import math as m
+math.sqrt(16) == m.sqrt(16) #=> True
+
+# Les modules Python sont juste des fichiers Python ordinaires.
+# On peut écrire ses propres modules et les importer.
+# Le nom du module doit être le même que le nom du fichier.
+
+# On peut trouver quelle fonction et attributs déterminent un module
+import math
+dir(math)
+
+
+```
+
+## Prêt à aller plus loin?
+
+### En ligne gratuitement
+
+* [Learn Python The Hard Way](http://learnpythonthehardway.org/book/)
+* [Dive Into Python](http://www.diveintopython.net/)
+* [The Official Docs](http://docs.python.org/2.6/)
+* [Hitchhiker's Guide to Python](http://docs.python-guide.org/en/latest/)
+* [Python Module of the Week](http://pymotw.com/2/)
+
+### Format papier
+
+* [Programming Python](http://www.amazon.com/gp/product/0596158106/ref=as_li_qf_sp_asin_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596158106&linkCode=as2&tag=homebits04-20)
+* [Dive Into Python](http://www.amazon.com/gp/product/1441413022/ref=as_li_tf_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=1441413022&linkCode=as2&tag=homebits04-20)
+* [Python Essential Reference](http://www.amazon.com/gp/product/0672329786/ref=as_li_tf_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0672329786&linkCode=as2&tag=homebits04-20)
+
diff --git a/fr-fr/racket-fr.html.markdown b/fr-fr/racket-fr.html.markdown
new file mode 100644
index 00000000..8b2420f8
--- /dev/null
+++ b/fr-fr/racket-fr.html.markdown
@@ -0,0 +1,628 @@
+---
+language: racket
+filename: learnracket-fr.rkt
+contributors:
+ - ["th3rac25", "https://github.com/voila"]
+ - ["Eli Barzilay", "https://github.com/elibarzilay"]
+ - ["Gustavo Schmidt", "https://github.com/gustavoschmidt"]
+translators:
+ - ["Xavier Nayrac", "https://github.com/lkdjiin"]
+lang: fr-fr
+---
+
+Racket est un langage de programmation généraliste, multi-paradigme,
+descendant de Lisp/Scheme.
+
+Les retours et commentaires sont appréciés ! Vous pouvez joindre l'auteur
+original ici :
+[@th3rac25](http://twitter.com/th3rac25) ou là : th3rac25 [at] [google's email
+service]. Vous pouvez joindre le traducteur de ce document ici :
+[@lkdjiin](http://twitter.com/lkdjiin).
+
+```racket
+#lang racket ; défini le dialecte à utiliser.
+
+;;; Commentaires
+
+;; Une ligne de commentaire commence par un point-virgule.
+
+#| Un bloc de commentaires
+ peut tenir sur plusieurs lignes…
+ #|
+ et on peut les imbriquer !
+ |#
+|#
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; 1. Types de données et opérateurs primitifs
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;;; Nombres
+9999999999999999999999 ; entier
+#b111 ; binaire => 7
+#o111 ; octal => 73
+#x111 ; hexadécimal => 273
+3.14 ; réel
+6.02e+23
+1/2 ; rationnel
+1+2i ; complexe
+
+;; Un appel de fonction s'écrit (f x y z ...)
+;; où f est une fonction et x, y, z, ... sont des arguments.
+;; Si vous voulez créer une liste littérales, utilisez ' pour
+;; empécher l'évaluation de la liste.
+'(+ 1 2) ; => (+ 1 2)
+;; Et maintenant, un peu d'arithmétique
+(+ 1 1) ; => 2
+(- 8 1) ; => 7
+(* 10 2) ; => 20
+(expt 2 3) ; => 8
+(quotient 5 2) ; => 2
+(remainder 5 2) ; => 1
+(/ 35 5) ; => 7
+(/ 1 3) ; => 1/3
+(exact->inexact 1/3) ; => 0.3333333333333333
+(+ 1+2i 2-3i) ; => 3-1i
+
+;;; Booléens
+#t ; pour vrai
+#f ; pour faux -- Toute autre valeur que #f est vraie
+(not #t) ; => #f
+(and 0 #f (error "doesn't get here")) ; => #f
+(or #f 0 (error "doesn't get here")) ; => 0
+
+;;; Caractères
+#\A ; => #\A
+#\λ ; => #\λ
+#\u03BB ; => #\λ
+
+;;; Une chaîne de caractères est un tableau de caractères de longueur
+;;; fixe.
+"Hello, world!"
+"Benjamin \"Bugsy\" Siegel" ; Le backslash est le caractère d'échappement
+"Foo\tbar\41\x21\u0021\a\r\n" ; Sont inclus les échappements de type C
+ ; et unicode
+"λx:(μα.α→α).xx" ; une chaîne peut inclure de l'unicode
+
+;; On peut ajouter une chaîne à une autre
+(string-append "Hello " "world!") ; => "Hello world!"
+
+;; Une chaîne peut être traitée comme une liste de caractères
+(string-ref "Apple" 0) ; => #\A
+
+;; format est utilisé pour formatter une chaîne
+(format "~a can be ~a" "strings" "formatted")
+
+;; L'affichage est tout simple
+(printf "I'm Racket. Nice to meet you!\n")
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; 2. Variables
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Vous pouvez créer une variable à l'aide de define
+;; Une variable peut contenir n'importe quel caractères, à l'exception
+;; de : ()[]{}",'`;#|\
+(define some-var 5)
+some-var ; => 5
+
+;; Vous pouvez aussi utiliser des caractères unicode
+(define ⊆ subset?)
+(⊆ (set 3 2) (set 1 2 3)) ; => #t
+
+;; Accéder à une variable non-initialisée provoque une exception
+; x ; => x: indéfini ...
+
+;; Déclaration locale : `me` est attaché à "Bob" seulement à l'intérieur
+;; de (let ...)
+(let ([me "Bob"])
+ "Alice"
+ me) ; => "Bob"
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; 3. Structures and Collections
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;; Structures
+(struct dog (name breed age))
+(define my-pet
+ (dog "lassie" "collie" 5))
+my-pet ; => #<dog>
+(dog? my-pet) ; => #t
+(dog-name my-pet) ; => "lassie"
+
+;;; Paires (non mutable)
+;; `cons` construit une paire, `car` et `cdr` extraient respectivement le
+;; premier et le second élément.
+(cons 1 2) ; => '(1 . 2)
+(car (cons 1 2)) ; => 1
+(cdr (cons 1 2)) ; => 2
+
+;;; Listes
+
+;; Les listes en Racket sont des structures de données de type *linked-list*,
+;; produites avec des paires assemblées avec `cons` et terminée par `null`
+;; (ou '()).
+(cons 1 (cons 2 (cons 3 null))) ; => '(1 2 3)
+;; `list` est un constructeur variadique plus commode à utiliser
+(list 1 2 3) ; => '(1 2 3)
+;; et un guillemet simple peut aussi être utilisé pour une liste littérale
+'(1 2 3) ; => '(1 2 3)
+
+;; On peut toujours utiliser `cons` pour ajouter un élément au début
+;; d'une liste
+(cons 4 '(1 2 3)) ; => '(4 1 2 3)
+
+;; Utilisez `append` pour ajouter une liste à une autre
+(append '(1 2) '(3 4)) ; => '(1 2 3 4)
+
+;; Une liste est un type très basique, il y a donc *beaucoup* de
+;; fonctionnalités qui leur sont dédiées, quelques exemples :
+(map add1 '(1 2 3)) ; => '(2 3 4)
+(map + '(1 2 3) '(10 20 30)) ; => '(11 22 33)
+(filter even? '(1 2 3 4)) ; => '(2 4)
+(count even? '(1 2 3 4)) ; => 2
+(take '(1 2 3 4) 2) ; => '(1 2)
+(drop '(1 2 3 4) 2) ; => '(3 4)
+
+;;; Vecteurs
+
+;; Un vecteur est un tableau de taille fixe
+#(1 2 3) ; => '#(1 2 3)
+
+;; Utilisez `vector-append` pour additionner des vecteurs entre eux
+(vector-append #(1 2 3) #(4 5 6)) ; => #(1 2 3 4 5 6)
+
+;;; Sets
+
+;; Créez un set à partir d'une liste
+(list->set '(1 2 3 1 2 3 3 2 1 3 2 1)) ; => (set 1 2 3)
+
+;; Ajoutez un membre avec `set-add`
+;; (Fonctionnel: renvoit le set étendu, plutôt que de muter le set en entrée)
+(set-add (set 1 2 3) 4) ; => (set 1 2 3 4)
+
+;; Retirez un membre avec `set-remove`
+(set-remove (set 1 2 3) 1) ; => (set 2 3)
+
+;; Testez l'existence d'un membre avec `set-member?`
+(set-member? (set 1 2 3) 1) ; => #t
+(set-member? (set 1 2 3) 4) ; => #f
+
+;;; Tables de hashage
+
+;; Créer une table de hashage non-mutable (un exemple mutable plus loin)
+(define m (hash 'a 1 'b 2 'c 3))
+
+;; Retrouver une valeur
+(hash-ref m 'a) ; => 1
+
+;; Chercher une valeur inexistante provoque une exceptions
+; (hash-ref m 'd) => no value found
+
+;; Vous pouvez fournir une valeur par défaut pour les clés manquantes
+(hash-ref m 'd 0) ; => 0
+
+;; Utilisez `hash-set` pour étendre une table de hashage non-mutable
+;; (Renvoit la table étendu, plutôt que de la muter)
+(define m2 (hash-set m 'd 4))
+m2 ; => '#hash((b . 2) (a . 1) (d . 4) (c . 3))
+
+;; Rappelez-vous, ces tables de hashage sont non-mutables !
+m ; => '#hash((b . 2) (a . 1) (c . 3)) <-- no `d'
+
+;; Utilisez `hash-remove` pour supprimer des clés (également fonctionnel)
+(hash-remove m 'a) ; => '#hash((b . 2) (c . 3))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; 3. Fonctions
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;; Utilisez `lambda` pour créer des fonctions.
+;; Une fonction renvoie toujours la valeur de sa dernière expression.
+(lambda () "Hello World") ; => #<procedure>
+;; On peut aussi utiliser le caractère unicode `λ'
+(λ () "Hello World") ; => même fonction
+
+;; Utilisez des parenthèses pour appeler toutes les fonctions, ce qui
+;; inclus aussi les expressions lambda
+((lambda () "Hello World")) ; => "Hello World"
+((λ () "Hello World")) ; => "Hello World"
+
+;; Assignez une fonction à une variable
+(define hello-world (lambda () "Hello World"))
+(hello-world) ; => "Hello World"
+
+;; Vous pouvez raccourcir ceci en utilisant le sucre syntaxique pour la
+;; définition de fonction :
+(define (hello-world2) "Hello World")
+
+;; Entre les () après lambda, vous déclarez la liste des arguments de la
+;; fonction
+(define hello
+ (lambda (name)
+ (string-append "Hello " name)))
+(hello "Steve") ; => "Hello Steve"
+;; … ou alors, en utilisant le sucre syntaxique, ce qui suit est équivalent
+(define (hello2 name)
+ (string-append "Hello " name))
+
+;; Vous pouvez obtenir des fonctions variadique en utilisant `case-lambda`
+(define hello3
+ (case-lambda
+ [() "Hello World"]
+ [(name) (string-append "Hello " name)]))
+(hello3 "Jake") ; => "Hello Jake"
+(hello3) ; => "Hello World"
+;; … ou spécifier des arguments optionnels avec une valeur par défaut
+(define (hello4 [name "World"])
+ (string-append "Hello " name))
+
+;; Les fonctions peuvent rassembler des arguments supplémentaires dans une
+;; liste
+(define (count-args . args)
+ (format "You passed ~a args: ~a" (length args) args))
+(count-args 1 2 3) ; => "You passed 3 args: (1 2 3)"
+;; … ou bien avec `lambda`, sans sucre syntaxique
+(define count-args2
+ (lambda args
+ (format "You passed ~a args: ~a" (length args) args)))
+
+;; Vous pouvez mixer arguments réguliers et supplémentaires
+(define (hello-count name . args)
+ (format "Hello ~a, you passed ~a extra args" name (length args)))
+(hello-count "Finn" 1 2 3)
+; => "Hello Finn, you passed 3 extra args"
+;; … sans sucre syntaxique
+(define hello-count2
+ (lambda (name . args)
+ (format "Hello ~a, you passed ~a extra args" name (length args))))
+
+;; Avec des mot-clés cette fois
+(define (hello-k #:name [name "World"] #:greeting [g "Hello"] . args)
+ (format "~a ~a, ~a extra args" g name (length args)))
+(hello-k) ; => "Hello World, 0 extra args"
+(hello-k 1 2 3) ; => "Hello World, 3 extra args"
+(hello-k #:greeting "Hi") ; => "Hi World, 0 extra args"
+(hello-k #:name "Finn" #:greeting "Hey") ; => "Hey Finn, 0 extra args"
+(hello-k 1 2 3 #:greeting "Hi" #:name "Finn" 4 5 6)
+ ; => "Hi Finn, 6 extra args"
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; 4. Égalité
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;; Pour les nombres, utilisez `=`
+(= 3 3.0) ; => #t
+(= 2 1) ; => #f
+
+;; Pour tester l'identité des objets, utilisez `eq?`
+(eq? 3 3) ; => #t
+(eq? 3 3.0) ; => #f
+(eq? (list 3) (list 3)) ; => #f
+
+;; Pour les collections, utilisez `equal?`
+(equal? (list 'a 'b) (list 'a 'b)) ; => #t
+(equal? (list 'a 'b) (list 'b 'a)) ; => #f
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; 5. Structures de contrôle
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;;; Conditions
+
+(if #t ; expression pour le test
+ "this is true" ; expression si vrai
+ "this is false") ; expression si faux
+; => "this is true"
+
+;; Dans les condition, toutes les valeurs non-fausses sont traitées commentaires
+;; étant vraies (c'est à dire toutes sauf #f)
+(member 'Groucho '(Harpo Groucho Zeppo)) ; => '(Groucho Zeppo)
+(if (member 'Groucho '(Harpo Groucho Zeppo))
+ 'yep
+ 'nope)
+; => 'yep
+
+;; `cond` permet d'enchaîner une série de tests afin d'obtenir un résultat
+(cond [(> 2 2) (error "wrong!")]
+ [(< 2 2) (error "wrong again!")]
+ [else 'ok]) ; => 'ok
+
+;;; Filtrage par motif (*pattern matching*)
+
+(define (fizzbuzz? n)
+ (match (list (remainder n 3) (remainder n 5))
+ [(list 0 0) 'fizzbuzz]
+ [(list 0 _) 'fizz]
+ [(list _ 0) 'buzz]
+ [_ #f]))
+
+(fizzbuzz? 15) ; => 'fizzbuzz
+(fizzbuzz? 37) ; => #f
+
+;;; Les boucles
+
+;; On peut boucler en utilisant la récursion (terminale)
+(define (loop i)
+ (when (< i 10)
+ (printf "i=~a\n" i)
+ (loop (add1 i))))
+(loop 5) ; => i=5, i=6, ...
+
+;; D'une manière similaire, avec un `let` nommé
+(let loop ((i 0))
+ (when (< i 10)
+ (printf "i=~a\n" i)
+ (loop (add1 i)))) ; => i=0, i=1, ...
+
+;; Voir plus loin pour l'ajout d'une nouvelle forme `loop`, mais Racket
+;; possède déjà une forme `for` flexible et élaborée pour les itérations
+(for ([i 10])
+ (printf "i=~a\n" i)) ; => i=0, i=1, ...
+(for ([i (in-range 5 10)])
+ (printf "i=~a\n" i)) ; => i=5, i=6, ...
+
+;;; Itérer sur autre chose que des nombres
+;; `for` permet d'itérer sur plein de type de séquences:
+;; listes, vecteurs, chaînes de caractères, sets, tables de hashage, etc
+
+(for ([i (in-list '(l i s t))])
+ (displayln i))
+
+(for ([i (in-vector #(v e c t o r))])
+ (displayln i))
+
+(for ([i (in-string "string")])
+ (displayln i))
+
+(for ([i (in-set (set 'x 'y 'z))])
+ (displayln i))
+
+(for ([(k v) (in-hash (hash 'a 1 'b 2 'c 3 ))])
+ (printf "key:~a value:~a\n" k v))
+
+;;; Itérations plus complexes
+
+;; Balayage parallèle de plusieurs séquences (on stoppe sur la plus petite)
+(for ([i 10] [j '(x y z)]) (printf "~a:~a\n" i j))
+; => 0:x 1:y 2:z
+
+;; Boucles imbriquées
+(for* ([i 2] [j '(x y z)]) (printf "~a:~a\n" i j))
+; => 0:x, 0:y, 0:z, 1:x, 1:y, 1:z
+
+;; Conditions dans les boucles
+(for ([i 1000]
+ #:when (> i 5)
+ #:unless (odd? i)
+ #:break (> i 10))
+ (printf "i=~a\n" i))
+; => i=6, i=8, i=10
+
+;;; Compréhensions de liste
+;; Très similaires aux boucles `for` -- renvoient en plus une collection
+
+(for/list ([i '(1 2 3)])
+ (add1 i)) ; => '(2 3 4)
+
+(for/list ([i '(1 2 3)] #:when (even? i))
+ i) ; => '(2)
+
+(for/list ([i 10] [j '(x y z)])
+ (list i j)) ; => '((0 x) (1 y) (2 z))
+
+(for/list ([i 1000] #:when (> i 5) #:unless (odd? i) #:break (> i 10))
+ i) ; => '(6 8 10)
+
+(for/hash ([i '(1 2 3)])
+ (values i (number->string i)))
+; => '#hash((1 . "1") (2 . "2") (3 . "3"))
+
+;; Il y a plein d'autres fonctions natives pour collecter des données à
+;; l'aide de boucles
+(for/sum ([i 10]) (* i i)) ; => 285
+(for/product ([i (in-range 1 11)]) (* i i)) ; => 13168189440000
+(for/and ([i 10] [j (in-range 10 20)]) (< i j)) ; => #t
+(for/or ([i 10] [j (in-range 0 20 2)]) (= i j)) ; => #t
+;; Et pour n'importe quell combinaison arbitraire, utilisez `for/fold`
+(for/fold ([sum 0]) ([i '(1 2 3 4)]) (+ sum i)) ; => 10
+;; (Ceci peut souvent remplacer des boucles communes de style impératif)
+
+;;; Exceptions
+
+;; Pour capturer une exception, utilisez la forme `with-handlers`
+(with-handlers ([exn:fail? (lambda (exn) 999)])
+ (+ 1 "2")) ; => 999
+(with-handlers ([exn:break? (lambda (exn) "no time")])
+ (sleep 3)
+ "phew") ; => "phew", but if you break it => "no time"
+
+;; Utilisez `raise` pour soulever une exception, ou encore n'importe quelle
+;; autre valeur
+(with-handlers ([number? ; capturer la valeur numérique soulevée
+ identity]) ; la renvoyer en tant que valeur simple
+ (+ 1 (raise 2))) ; => 2
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; 6. Mutabilité
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;; Utilisez `set!` pour réassigner une valeur à une variable existante
+(define n 5)
+(set! n (add1 n))
+n ; => 6
+
+;; Utilisez le mécanisme des boites (*box*) pour les valeurs explicitement
+;; mutables (similaire aux pointeurs ou références dans d'autres langages)
+(define n* (box 5))
+(set-box! n* (add1 (unbox n*)))
+(unbox n*) ; => 6
+
+;; Beaucoup de types de données en Racket sont non-mutables (paires, listes,
+;; etc), certains ont à la fois une version mutable et une version
+;; non-mutable (chaînes, vecteurs, tables de hashage, etc)
+
+;; Utilisez `vector` ou `make-vector` pour créer des vecteurs mutables
+(define vec (vector 2 2 3 4))
+(define wall (make-vector 100 'bottle-of-beer))
+;; Utilisez `vector-set!` pour mettre à jour un emplacement
+(vector-set! vec 0 1)
+(vector-set! wall 99 'down)
+vec ; => #(1 2 3 4)
+
+;; Créer une table de hashage mutable vide et la manipuler
+(define m3 (make-hash))
+(hash-set! m3 'a 1)
+(hash-set! m3 'b 2)
+(hash-set! m3 'c 3)
+(hash-ref m3 'a) ; => 1
+(hash-ref m3 'd 0) ; => 0
+(hash-remove! m3 'a)
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; 7. Modules
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;; Les modules permettent d'organiser le code en plusieurs fichiers
+;; et bibliothèques réutilisables. Ici, nous utiliserons des sous-modules,
+;; imbriqués dans le grand module que forme ce texte (qui démarre à la
+;; ligne `#lang`).
+
+(module cake racket/base ; défini un module `cake', basé sur racket/base
+
+ (provide print-cake) ; fonction exportée par le module (publique)
+
+ (define (print-cake n)
+ (show " ~a " n #\.)
+ (show " .-~a-. " n #\|)
+ (show " | ~a | " n #\space)
+ (show "---~a---" n #\-))
+
+ (define (show fmt n ch) ; fonction interne/privée
+ (printf fmt (make-string n ch))
+ (newline)))
+
+;; Utilisez `require` pour importer les fonctions fournies par un
+;; module (provide)
+(require 'cake) ; le ' est pour un sous-module local
+(print-cake 3)
+; (show "~a" 1 #\A) ; => erreur, `show` n'est pas exportée
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; 8. Classes et objets
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;; Créer une classe fish% (% est idiomatique pour les noms de classes)
+(define fish%
+ (class object%
+ (init size) ; argument pour l'initialisation
+ (super-new) ; initialisation de la super-classe
+ ;; Les champs/membres/variables de classe
+ (define current-size size)
+ ;; Méthodes publiques
+ (define/public (get-size)
+ current-size)
+ (define/public (grow amt)
+ (set! current-size (+ amt current-size)))
+ (define/public (eat other-fish)
+ (grow (send other-fish get-size)))))
+
+;; Créer une instance de fish%
+(define charlie
+ (new fish% [size 10]))
+
+;; Utilisez `send` pour appeler une méthode d'un objet
+(send charlie get-size) ; => 10
+(send charlie grow 6)
+(send charlie get-size) ; => 16
+
+;; `fish%` est une simple valeur de «première classe», ce qui va permettre
+;; la composition (*mixins*)
+(define (add-color c%)
+ (class c%
+ (init color)
+ (super-new)
+ (define my-color color)
+ (define/public (get-color) my-color)))
+(define colored-fish% (add-color fish%))
+(define charlie2 (new colored-fish% [size 10] [color 'red]))
+(send charlie2 get-color)
+;; ou, sans les noms:
+(send (new (add-color fish%) [size 10] [color 'red]) get-color)
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; 9. Macros
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;; Les macros permettent d'étendre la syntaxe du langage
+
+;; Ajoutons une boucle `loop`
+(define-syntax-rule (while condition body ...)
+ (let loop ()
+ (when condition
+ body ...
+ (loop))))
+
+(let ([i 0])
+ (while (< i 10)
+ (displayln i)
+ (set! i (add1 i))))
+
+;; Les macros sont hygiéniques, vous ne pouvez pas *clasher* avec les
+;; variables existantes !
+(define-syntax-rule (swap! x y) ; ! est idiomatique pour la mutation
+ (let ([tmp x])
+ (set! x y)
+ (set! y tmp)))
+
+(define tmp 2)
+(define other 3)
+(swap! tmp other)
+(printf "tmp = ~a; other = ~a\n" tmp other)
+;; La variable `tmp` est renommée en `tmp_1`
+;; dans le but d'éviter un conflit de nom
+;; (let ([tmp_1 tmp])
+;; (set! tmp other)
+;; (set! other tmp_1))
+
+;; Mais il faut quand même faire bien attention avec les macros, par exemple:
+(define-syntax-rule (bad-while condition body ...)
+ (when condition
+ body ...
+ (bad-while condition body ...)))
+;; cette macro est cassée : ell génère un code infini, si vous l'essayez
+;; le compilateur va entrer dans une boucle infinie.
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; 10. Contrats
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;; Les contrats imposent des contraintes aux valeurs exportées depuis
+;; les modules
+
+(module bank-account racket
+ (provide (contract-out
+ [deposit (-> positive? any)] ; un dépot est toujours positif
+ [balance (-> positive?)]))
+
+ (define amount 0)
+ (define (deposit a) (set! amount (+ amount a)))
+ (define (balance) amount)
+ )
+
+(require 'bank-account)
+(deposit 5)
+
+(balance) ; => 5
+
+;; Les clients qui essaient de déposer un montant non-positif sont blamés
+;; (deposit -5) ; => deposit: contract violation
+;; expected: positive?
+;; given: -5
+;; more details....
+```
+
+## Pour aller plus loin
+
+Vous en voulez plus ? Essayez
+[Getting Started with Racket](http://docs.racket-lang.org/getting-started/)
diff --git a/fr-fr/ruby-fr.html.markdown b/fr-fr/ruby-fr.html.markdown
new file mode 100644
index 00000000..3060bd75
--- /dev/null
+++ b/fr-fr/ruby-fr.html.markdown
@@ -0,0 +1,411 @@
+---
+language: ruby
+filename: learnruby-fr.rb
+contributors:
+ - ["David Underwood", "http://theflyingdeveloper.com"]
+ - ["Joel Walden", "http://joelwalden.net"]
+ - ["Luke Holder", "http://twitter.com/lukeholder"]
+ - ["Tristan Hume", "http://thume.ca/"]
+ - ["Nick LaMuro", "https://github.com/NickLaMuro"]
+translators:
+ - ["Geoffrey Roguelon", "https://github.com/GRoguelon"]
+ - ["Nami-Doc", "https://github.com/Nami-Doc"]
+lang: fr-fr
+---
+
+```ruby
+# Ceci est un commentaire
+
+=begin
+Ceci est un commentaire multiligne
+Personne ne les utilise
+Vous devriez en faire de même
+=end
+
+# Tout d'abord : Tout est un objet.
+
+# Les nombres sont des objets
+
+3.class #=> Fixnum
+
+3.to_s #=> "3"
+
+# Les opérateurs de base
+1 + 1 #=> 2
+8 - 1 #=> 7
+10 * 2 #=> 20
+35 / 5 #=> 7
+
+# Les opérateurs sont juste des raccourcis
+# pour appeler une méthode sur un objet
+1.+(3) #=> 4
+10.* 5 #=> 50
+
+# Les valeurs spéciales sont des objets
+nil # Nul
+true # Vrai
+false # Faux
+
+nil.class #=> NilClass
+true.class #=> TrueClass
+false.class #=> FalseClass
+
+# Égalité
+1 == 1 #=> true
+2 == 1 #=> false
+
+# Inégalité
+1 != 1 #=> false
+2 != 1 #=> true
+!true #=> false
+!false #=> true
+
+# à part false lui-même, nil est la seule autre valeur 'false'
+
+!nil #=> true
+!false #=> true
+!0 #=> false
+
+# Plus de comparaisons
+1 < 10 #=> true
+1 > 10 #=> false
+2 <= 2 #=> true
+2 >= 2 #=> true
+
+# Les chaînes de caractères sont des objets
+
+'Je suis une chaîne de caractères'.class #=> String
+"Je suis également une chaîne de caractères".class #=> String
+
+placeholder = "utiliser l'interpolation de chaîne de caractères"
+"Je peux #{placeholder} quand j'utilise les guillemets"
+#=> "Je peux utiliser l'interpolation de chaîne de caractères quand j'utilise les guillemets"
+
+# Affichez un message
+puts "J'affiche à l'écran!"
+
+# Variables
+x = 25 #=> 25
+x #=> 25
+
+# Notez que l'affectation retourne la valeur affectée.
+# Cela signifie que vous pouvez affecter plusieurs fois de suite :
+
+x = y = 10 #=> 10
+x #=> 10
+y #=> 10
+
+# Par convention, utilisez la notation underscore
+# pour nommer les variables
+snake_case = true
+
+# Utilisez des noms de variable explicites
+path_to_project_root = '/nom/correct/'
+path = '/mauvais/nom/'
+
+# Symboles (aussi des objets)
+# Les symboles sont immuables, constants,
+# réutilisables et représentés en interne
+# par une valeur entière. Ils sont souvent
+# utilisés à la place des chaînes de caractères
+# pour transmettre efficacement des valeurs
+# spécifiques ou significatives
+
+:pending.class #=> Symbol
+
+status = :pending
+
+status == :pending #=> true
+
+status == 'pending' #=> false
+
+status == :approved #=> false
+
+# Tableaux
+
+# Ceci est un tableau
+array = [1, 2, 3, 4, 5] #=> [1, 2, 3, 4, 5]
+
+# Les tableaux contiennent différents types d'élément.
+
+[1, "hello", false] #=> [1, "hello", false]
+
+# Les tableaux peuvent être indexés
+# Du début
+array[0] #=> 1
+array[12] #=> nil
+
+# Comme les opérateurs, la syntaxe [var] est juste un raccourci
+# pour appeler la méthode [] d'un objet
+array.[] 0 #=> 1
+array.[] 12 #=> nil
+
+# Depuis la fin
+array[-1] #=> 5
+
+# Avec un index de début et de fin
+array[2, 4] #=> [3, 4, 5]
+
+# Ou avec un intervalle
+array[1..3] #=> [2, 3, 4]
+
+# Ajoutez un élément au tableau comme ceci
+array << 6 #=> [1, 2, 3, 4, 5, 6]
+
+# Les Hash sont des dictionnaires Ruby contenant des paires de clé/valeur.
+# Les Hash sont délimitées par des accolades :
+hash = {'color' => 'green', 'number' => 5}
+
+hash.keys #=> ['color', 'number']
+
+# Les Hash retournent la valeur
+# en utilisant la clé associée à la valeur :
+hash['color'] #=> 'green'
+hash['number'] #=> 5
+
+# Recherchez une clé inexistante dans une Hash retourne nil :
+hash['nothing here'] #=> nil
+
+# Depuis Ruby 1.9, Une syntaxe spécifique est apparue
+# en utilisant les symboles comme clés :
+
+new_hash = { defcon: 3, action: true}
+
+new_hash.keys #=> [:defcon, :action]
+
+# Astuce : Les tableaux et les Hash sont dénombrables
+# Ils partagent un certain nombre de méthodes pratiques
+# telle que each, map, count, etc...
+
+# Structures de contrôle
+
+if true
+ "si instruction"
+elsif false
+ "autrement si, facultatif"
+else
+ "autrement, également facultatif"
+end
+
+for compteur in 1..5
+ puts "itération #{compteur}"
+end
+#=> itération 1
+#=> itération 2
+#=> itération 3
+#=> itération 4
+#=> itération 5
+
+# CEPENDANT, l'usage de la boucle for est très rare.
+# À la place, utilisez la méthode "each"
+# et passez lui un bloc de code.
+# Un bloc de code est un ensemble d'instructions
+# que vous pouvez passer à une methode comme "each".
+# Les blocs sont similaires aux lambdas, aux fonctions anonymes
+# ou encore aux closures dans d'autres langages.
+#
+# La méthode "each" exécute le bloc de code
+# pour chaque élément de l'intervalle d'éléments.
+# Le bloc de code passe un paramètre compteur.
+# Appelez la méthode "each" avec un bloc de code comme ceci :
+
+(1..5).each do |compteur|
+ puts "itération #{compteur}"
+end
+#=> itération 1
+#=> itération 2
+#=> itération 3
+#=> itération 4
+#=> itération 5
+
+# Vous pouvez également mettre un bloc de code entre accolades :
+(1..5).each {|compteur| puts "itération #{compteur}"}
+
+# Le contenu des structures de données peut être parcouru
+# en utilisant la méthode each.
+array.each do |element|
+ puts "#{element} est une partie du tableau"
+end
+hash.each do |cle, valeur|
+ puts "#{cle} est #{valeur}"
+end
+
+compteur = 1
+while compteur <= 5 do
+ puts "itération #{compteur}"
+ compteur += 1
+end
+#=> itération 1
+#=> itération 2
+#=> itération 3
+#=> itération 4
+#=> itération 5
+
+grade = 'B'
+
+case grade
+when 'A'
+ puts "Excellent"
+when 'B'
+ puts "Plus de chance la prochaine fois"
+when 'C'
+ puts "Vous pouvez faire mieux"
+when 'D'
+ puts "C'est pas terrible"
+when 'F'
+ puts "Vous avez échoué!"
+else
+ puts "Sytème de notation alternatif"
+end
+
+# Fonctions
+
+def double(x)
+ x * 2
+end
+
+# Les fonctions (et tous les blocs de code) retournent
+# implicitement la valeur de la dernière instruction évaluée
+double(2) #=> 4
+
+# Les paranthèses sont facultative
+# lorsqu'il n'y a pas d'ambiguïté sur le résultat
+double 3 #=> 6
+
+double double 3 #=> 12
+
+def sum(x,y)
+ x + y
+end
+
+# Les paramètres de méthode sont séparés par des virgules
+sum 3, 4 #=> 7
+
+sum sum(3,4), 5 #=> 12
+
+# yield
+# Toutes les méthodes ont un argument facultatif et implicite
+# de type bloc de code
+# il peut être appelé avec le mot clé 'yield'
+
+def surround
+ puts "{"
+ yield
+ puts "}"
+end
+
+surround { puts 'Bonjour tout le monde' }
+
+# {
+# Bonjour tout le monde
+# }
+
+
+# Définissez une classe avec le mot clé 'class'
+class Humain
+
+ # Une variable de classe
+ # est partagée par toutes les instances de cette classe.
+ @@espece = "H. sapiens"
+
+ # Constructeur de classe
+ def initialize(nom, age = 0)
+ # Affectez l'argument à la variable d'instance 'nom'
+ # pour la durée de vie de l'instance de cette classe
+ @nom = nom
+ # Si le paramètre 'age' est absent,
+ # la valeur par défaut définie dans la liste des arguments sera utilisée.
+ @age = age
+ end
+
+ # Une simple méthode setter
+ def nom=(nom)
+ @nom = nom
+ end
+
+ # Une simple méthode getter
+ def nom
+ @nom
+ end
+
+ # Une méthode de classe utilise le mot clé 'self'
+ # pour se distinguer de la méthode d'instance.
+ # La méthode sera alors accessible à partir de la classe
+ # et non pas de l'instance.
+ def self.say(msg)
+ puts "#{msg}"
+ end
+
+ def species
+ @@species
+ end
+
+end
+
+
+# Instanciez une classe
+jim = Humain.new("Jim Halpert")
+
+dwight = Humain.new("Dwight K. Schrute")
+
+# Appelez quelques méthodes
+jim.espece #=> "H. sapiens"
+jim.nom #=> "Jim Halpert"
+jim.nom = "Jim Halpert II" #=> "Jim Halpert II"
+jim.nom #=> "Jim Halpert II"
+dwight.espece #=> "H. sapiens"
+dwight.nom #=> "Dwight K. Schrute"
+
+# Appelez la méthode de classe
+Humain.say("Hi") #=> "Hi"
+
+# Les classes sont également des objets en Ruby.
+# Par conséquent, les classes peuvent avoir des variables d'instance.
+# Les variables de classe sont partagées parmi
+# la classe et ses descendants.
+
+# Classe parente
+class Humain
+ @@foo = 0
+
+ def self.foo
+ @@foo
+ end
+
+ def self.foo=(valeur)
+ @@foo = valeur
+ end
+end
+
+# Classe fille
+class Travailleur < Humain
+end
+
+Humain.foo # 0
+Travailleur.foo # 0
+
+Humain.foo = 2 # 2
+Travailleur.foo # 2
+
+# Les variables d'instance de classe ne sont pas partagées
+# avec les classes héritées.
+
+class Humain
+ @bar = 0
+
+ def self.bar
+ @bar
+ end
+
+ def self.bar=(valeur)
+ @bar = valeur
+ end
+end
+
+class Docteur < Humain
+end
+
+Humain.bar # 0
+Docteur.bar # nil
+
+```