Il existe des centaines de langages de programmation. Ils ne s’écrivent pas de la même façon, mais la plupart offrent les mêmes constructions élémentaires, c’est-à-dire les briques de base de tout programme : l’affectation, la condition, la boucle et l’appel de fonction.
Un programme est une suite d’instructions. Une instruction est un ordre donné à l’ordinateur : somme = 0 (une affectation), print(somme) (un appel de fonction) ou return somme sont des instructions. Selon les langages, chaque instruction occupe une ligne ou se termine par un signe de ponctuation.
Pour le constater, on écrit le même programme dans dix-huit langages. Ce programme calcule la moyenne des notes d’au moins 10 dans la liste [12, 7, 15, 9, 18, 10], c’est-à-dire la moyenne de 12, 15, 18 et 10 : (12 + 15 + 18 + 10) ÷ 4 = 13,75. Les programmes affichent 13.75, car en programmation la partie décimale d’un nombre est séparée par un point.
Chaque onglet de l’éditeur montre une version du programme. Sous le code, la bande du bas donne la commande à taper dans un terminal pour exécuter le programme, puis ce que le programme affiche. Sous l’éditeur, deux listes comparent le langage choisi avec Python. Le dernier onglet, « Événementiel », montre une page web qui calcule la moyenne quand on clique sur un bouton : on peut y modifier les notes.
1def moyenne_admis(notes):
2 somme = 0
3 nombre = 0
4 for note in notes:
5 if note >= 10:
6 somme = somme + note
7 nombre = nombre + 1
8 return somme / nombre
9
10
11notes = [12, 7, 15, 9, 18, 10]
12print(f"Moyenne des notes d'au moins 10 : {moyenne_admis(notes)}")
: et se repère à son indentation : les lignes décalées vers la droite font partie du bloc.somme contient un entier./ donne toujours un nombre à virgule : 55 / 4 vaut 13.75.python3 lit les instructions une à une et les exécute aussitôt. 1#include <stdio.h>
2
3double moyenne_admis(int notes[], int taille) {
4 int somme = 0;
5 int nombre = 0;
6 for (int i = 0; i < taille; i++) {
7 if (notes[i] >= 10) {
8 somme = somme + notes[i];
9 nombre = nombre + 1;
10 }
11 }
12 return (double) somme / nombre;
13}
14
15int main(void) {
16 int notes[] = {12, 7, 15, 9, 18, 10};
17 printf("Moyenne des notes d'au moins 10 : %.2f\n", moyenne_admis(notes, 6));
18 return 0;
19}
>= et la même affectation somme = somme + ....#include <stdio.h>, est remplacée avant la compilation par le contenu du fichier stdio.h (pour standard input/output, « entrées et sorties standard »). Ce fichier, fourni avec le C, déclare les fonctions d’affichage et de lecture, dont printf : sans cette ligne, le compilateur refuse d’utiliser printf. C’est l’équivalent d’un import en Python.int pour un entier, double pour un nombre à virgule. Une variable déclarée int ne peut contenir qu’un entier.double signifie « double précision » : en pratique, un double occupe 64 bits, deux fois plus qu’un float, le type à virgule en simple précision (32 bits). Le cours « 05 - Réels »
présente ce format de la norme IEEE 754, qui est aussi celui du float de Python. Le mot est plus ancien que cette norme : il vient du langage Fortran, qui avait déjà un type DOUBLE PRECISION dans les années 1960.{ }, et chaque instruction (affectation, appel de fonction, return) se termine par un point-virgule.int notes[]), l’équivalent d’une liste Python dont le nombre d’éléments ne peut pas changer.len. On lui transmet donc ce nombre, 6, dans un second paramètre, taille.for (int i = 0; i < taille; i++) fait prendre à i les valeurs 0, 1, …, taille - 1, comme for i in range(taille) en Python ; notes[i] est la note placée à la position i.(double) somme transforme l’entier somme en nombre à virgule avant la division : en C, la division de deux entiers donne un entier (55 / 4 vaudrait 13).gcc traduit tout le programme en instructions du processeur et crée le fichier exécutable moyenne, que l’on lance avec ./moyenne. L’exécution commence toujours par la fonction main.int main(void), int est le type de ce que renvoie main, et void signifie qu’elle ne reçoit aucun argument. return 0; renvoie au système d’exploitation le code de retour 0, qui signifie « tout s’est bien passé » ; un autre nombre signale une erreur. C’est ce code que lit le && de la commande gcc moyenne.c -o moyenne && ./moyenne : ./moyenne n’est lancé que si gcc a renvoyé 0, c’est-à-dire si la compilation a réussi. Depuis 1999, la norme du C permet d’omettre return 0; à la fin de main : le programme renvoie alors 0. Python, lui, renvoie 0 tout seul à la fin du programme. 1#include <iostream>
2#include <vector>
3
4double moyenne_admis(const std::vector<int>& notes) {
5 int somme = 0;
6 int nombre = 0;
7 for (int note : notes) {
8 if (note >= 10) {
9 somme = somme + note;
10 nombre = nombre + 1;
11 }
12 }
13 return static_cast<double>(somme) / nombre;
14}
15
16int main() {
17 std::vector<int> notes = {12, 7, 15, 9, 18, 10};
18 std::cout << "Moyenne des notes d'au moins 10 : " << moyenne_admis(notes) << std::endl;
19 return 0;
20}
for (int note : notes) se lit « pour chaque note de notes », comme for note in notes.int, double), les blocs sont délimités par des accolades, chaque instruction se termine par un point-virgule, et l’exécution commence par la fonction main.return 0; à la fin de main renvoie au système d’exploitation le code de retour 0, qui signifie « tout s’est bien passé ». En C++, cette ligne peut être omise dans main : le programme renvoie alors 0.std::vector<int> est une liste d’entiers qui connaît son nombre d’éléments et peut grandir, contrairement au tableau du C : il n’est donc plus nécessaire de transmettre le nombre de notes à la fonction.const std::vector<int>& notes, le signe & indique que la fonction utilise la liste sans la recopier, et const qu’elle ne la modifiera pas.std:: indique que vector et cout viennent de la bibliothèque standard du C++ ; les lignes #include <iostream> et #include <vector> chargent les parties de cette bibliothèque dont le programme a besoin, comme #include <stdio.h> en C.std::cout << ... affiche : chaque signe << envoie un morceau (le texte, puis la moyenne) vers l’écran, et std::endl passe à la ligne.static_cast<double>(somme) transforme l’entier en nombre à virgule avant la division ; c’est l’écriture C++ de (double) somme.g++ crée le fichier exécutable moyenne. C’est le langage de nombreux logiciels où la rapidité compte : jeux vidéo, navigateurs web, logiciels de calcul. 1function moyenneAdmis(notes) {
2 let somme = 0;
3 let nombre = 0;
4 for (const note of notes) {
5 if (note >= 10) {
6 somme = somme + note;
7 nombre = nombre + 1;
8 }
9 }
10 return somme / nombre;
11}
12
13const notes = [12, 7, 15, 9, 18, 10];
14console.log(`Moyenne des notes d'au moins 10 : ${moyenneAdmis(notes)}`);
for (const note of notes) parcourt directement les notes, comme for note in notes.${...} insère une valeur, comme {...} dans une f-string.let crée une variable dont la valeur peut changer ; const (pour « constante ») crée une variable dont la valeur ne change plus.function introduit une fonction, comme def en Python.console.log affiche un texte, comme print. 1function moyenneAdmis(notes: number[]): number {
2 let somme = 0;
3 let nombre = 0;
4 for (const note of notes) {
5 if (note >= 10) {
6 somme = somme + note;
7 nombre = nombre + 1;
8 }
9 }
10 return somme / nombre;
11}
12
13const notes: number[] = [12, 7, 15, 9, 18, 10];
14console.log(`Moyenne des notes d'au moins 10 : ${moyenneAdmis(notes)}`);
for (const note of notes) parcourt directement les notes, comme for note in notes.${...} insère une valeur, comme {...} dans une f-string.somme et nombre n’est pas écrit : le compilateur le déduit de la valeur 0.: number[] et : number, on retrouve exactement la version JavaScript.notes: number[] indique que le paramètre est un tableau de nombres, et ): number que la fonction renvoie un nombre.tsc vérifie les types avant l’exécution : l’appel moyenneAdmis("12 7 15") est refusé, car un texte n’est pas un tableau de nombres. Il traduit ensuite le programme en JavaScript : tsc moyenne.ts crée le fichier moyenne.js, que node exécute.npm install -g typescript. 1public class Moyenne {
2
3 static double moyenneAdmis(int[] notes) {
4 int somme = 0;
5 int nombre = 0;
6 for (int note : notes) {
7 if (note >= 10) {
8 somme = somme + note;
9 nombre = nombre + 1;
10 }
11 }
12 return (double) somme / nombre;
13 }
14
15 public static void main(String[] args) {
16 int[] notes = {12, 7, 15, 9, 18, 10};
17 System.out.println("Moyenne des notes d'au moins 10 : " + moyenneAdmis(notes));
18 }
19}
for (int note : notes) se lit « pour chaque note de notes ».note >= 10.Moyenne : en Java, aucune fonction ne peut exister en dehors d’une classe. C’est la marque du style orienté objet, présenté plus bas.int, double, ou int[] pour un tableau d’entiers. Le type de la valeur renvoyée est écrit devant le nom de la fonction : double moyenneAdmis.main, écrite public static void main. void signifie que la méthode ne renvoie rien. public signifie qu’elle peut être utilisée depuis l’extérieur de la classe : c’est ce qui permet à la machine virtuelle Java de la lancer.static signifie que la méthode appartient à la classe elle-même et peut être appelée directement. Sans ce mot, il faudrait d’abord fabriquer un objet à partir de la classe, ce que l’on apprend en terminale. C’est pourquoi moyenneAdmis, appelée par main, est elle aussi déclarée static.System.out.println affiche un texte. Le signe + met bout à bout le texte et la moyenne : Java transforme automatiquement le nombre 13.75 en texte. En Python, "Moyenne : " + 13.75 provoque une erreur (TypeError) ; il faut écrire str(13.75) ou utiliser une f-string.javac, puis exécuté par la machine virtuelle Java avec la commande java Moyenne (voir la section « Interpréter ou compiler », sous l’éditeur). 1package main
2
3import "fmt"
4
5func moyenneAdmis(notes []int) float64 {
6 somme := 0
7 nombre := 0
8 for _, note := range notes {
9 if note >= 10 {
10 somme = somme + note
11 nombre = nombre + 1
12 }
13 }
14 return float64(somme) / float64(nombre)
15}
16
17func main() {
18 notes := []int{12, 7, 15, 9, 18, 10}
19 fmt.Println("Moyenne des notes d'au moins 10 :", moyenneAdmis(notes))
20}
if note >= 10.:= crée une variable et lui donne sa première valeur ; Go en déduit le type, ici un entier.somme = 2.5 serait refusé à la compilation, car somme est un entier. En Go, une variable a toujours un type, même quand on ne l’écrit pas.notes []int est une liste d’entiers. Le type de la valeur renvoyée suit les parenthèses : float64, un nombre à virgule.func introduit une fonction, comme def en Python.range notes fournit la position et la note ; le tiret bas _ indique que la position n’est pas utilisée.float64(...).import "fmt" charge la bibliothèque fmt, qui fournit la fonction d’affichage fmt.Println. Go est compilé : go run compile le programme puis l’exécute aussitôt. 1fn moyenne_admis(notes: &[i32]) -> f64 {
2 let mut somme = 0;
3 let mut nombre = 0;
4 for ¬e in notes {
5 if note >= 10 {
6 somme = somme + note;
7 nombre = nombre + 1;
8 }
9 }
10 somme as f64 / nombre as f64
11}
12
13fn main() {
14 let notes = [12, 7, 15, 9, 18, 10];
15 println!("Moyenne des notes d'au moins 10 : {}", moyenne_admis(¬es));
16}
for ... in parcourt les notes, comme en Python.mut (pour « modifiable ») : let mut somme = 0.fn introduit une fonction, comme def en Python. Les types s’écrivent après le nom : i32 désigne un entier et f64 un nombre à virgule ; le type de la valeur renvoyée suit la flèche ->.&, dans le type &[i32] et dans l’appel moyenne_admis(¬es), indique que la fonction consulte le tableau des notes sans en faire une copie.return.as f64 transforme un entier en nombre à virgule avant la division.println! affiche un texte ; les accolades {} marquent l’endroit où la moyenne s’insère.rustc crée le fichier exécutable moyenne, que l’on lance avec ./moyenne. 1fun moyenneAdmis(notes: List<Int>): Double {
2 var somme = 0
3 var nombre = 0
4 for (note in notes) {
5 if (note >= 10) {
6 somme = somme + note
7 nombre = nombre + 1
8 }
9 }
10 return somme.toDouble() / nombre
11}
12
13fun main() {
14 val notes = listOf(12, 7, 15, 9, 18, 10)
15 println("Moyenne des notes d'au moins 10 : ${moyenneAdmis(notes)}")
16}
for (note in notes) se lit comme for note in notes.${...} insère la valeur de la moyenne, comme {...} dans une f-string.var crée une variable dont la valeur peut changer ; val crée une variable en lecture seule, dont la valeur ne change plus. Ce sont les mots de la documentation de Kotlin.fun introduit une fonction, comme def en Python.notes: List<Int> est une liste d’entiers. Le type de la valeur renvoyée suit les parenthèses : : Double, un nombre à virgule.toDouble() transforme l’entier en nombre à virgule avant la division.kotlinc), puis exécuté par la machine virtuelle Java. 1func moyenneAdmis(_ notes: [Int]) -> Double {
2 var somme = 0
3 var nombre = 0
4 for note in notes {
5 if note >= 10 {
6 somme = somme + note
7 nombre = nombre + 1
8 }
9 }
10 return Double(somme) / Double(nombre)
11}
12
13let notes = [12, 7, 15, 9, 18, 10]
14print("Moyenne des notes d'au moins 10 : \(moyenneAdmis(notes))")
for note in notes et if note >= 10, sans parenthèses, comme en Python.var crée une variable, dont la valeur peut changer ; let crée une constante, dont la valeur ne change plus. Ce sont les mots de la documentation de Swift.func introduit une fonction ; le type de la valeur renvoyée est annoncé par une flèche : -> Double, un nombre à virgule._ notes: [Int], une liste d’entiers. Par défaut, Swift oblige à écrire le nom du paramètre à chaque appel : moyenneAdmis(notes: notes). Le tiret bas _ supprime cette obligation, et l’on écrit simplement moyenneAdmis(notes). Python accepte aussi l’écriture moyenne_admis(notes=notes), mais sans l’imposer.Double(somme) transforme l’entier en nombre à virgule avant la division.\(...) insère une valeur, comme {...} dans une f-string.1moyenneAdmis :: [Int] -> Double
2moyenneAdmis notes = fromIntegral (sum admis) / fromIntegral (length admis)
3 where
4 admis = filter (>= 10) notes
5
6main :: IO ()
7main = do
8 let notes = [12, 7, 15, 9, 18, 10]
9 putStrLn ("Moyenne des notes d'au moins 10 : " ++ show (moyenneAdmis notes))
moyenneAdmis, reçoit la liste des notes et renvoie la moyenne ; main affiche le résultat.sum et length jouent le même rôle que sum et len en Python.admis = [note for note in notes if note >= 10], suivie de return sum(admis) / len(admis).moyenneAdmis :: [Int] -> Double annonce le type de la fonction. :: se lit « a pour type » ; [Int] est une liste d’entiers ; la flèche -> sépare ce que la fonction reçoit (à gauche) de ce qu’elle renvoie (à droite), ici un nombre à virgule, Double.(>= 10) est une comparaison à laquelle il manque le nombre de gauche : c’est donc une fonction, qui reçoit une note et répond True si elle est supérieure ou égale à 10, False sinon.filter (>= 10) notes applique ce test à chaque note et construit la liste des notes pour lesquelles il répond True : [12, 15, 18, 10].moyenneAdmis notes correspond à moyenne_admis(notes) en Python, et dans filter (>= 10) notes, la fonction filter reçoit deux arguments. Les parenthèses servent seulement à regrouper : fromIntegral (sum admis) applique fromIntegral au résultat de sum admis./ n’accepte pas les entiers : fromIntegral transforme donc la somme (55) et le nombre de notes (4) en nombres à virgule avant de diviser. Pour une division entière, Haskell utilise une autre fonction, div.where donne un nom, admis, à une valeur utilisée dans le calcul. Ce nom est défini après la formule qui l’utilise : en Haskell, l’ordre des définitions n’a pas d’importance.main forment le programme proprement dit. main :: IO () annonce une action, c’est-à-dire un calcul qui communique avec l’extérieur, ici pour afficher. do enchaîne plusieurs étapes, let donne un nom à la liste des notes, et putStrLn affiche une ligne de texte.++ met deux textes bout à bout et show transforme la moyenne en texte, comme str() en Python.moyenneAdmis ne fait que calculer : elle ne peut ni afficher, ni modifier quoi que ce soit, et elle donne toujours le même résultat pour les mêmes arguments. Tout ce qui touche à l’extérieur est réservé aux actions comme main.runghc exécute directement le programme ; le compilateur ghc permet aussi d’en faire un fichier exécutable. 1let rec somme_et_nombre notes =
2 match notes with
3 | [] -> (0, 0)
4 | note :: reste ->
5 let (somme, nombre) = somme_et_nombre reste in
6 if note >= 10 then (somme + note, nombre + 1) else (somme, nombre)
7
8let moyenne_admis notes =
9 let (somme, nombre) = somme_et_nombre notes in
10 float_of_int somme /. float_of_int nombre
11
12let () =
13 let notes = [12; 7; 15; 9; 18; 10] in
14 Printf.printf "Moyenne des notes d'au moins 10 : %g\n" (moyenne_admis notes)
moyenne_admis, reçoit la liste des notes et renvoie la moyenne ; les noms s’écrivent avec des tirets bas, comme en Python.if ... then ... else ... choisit entre deux possibilités, comme if et else en Python.let lie un nom à une valeur (let notes = ...) ou à une fonction (let moyenne_admis notes = ...) : on parle de liaison. Une liaison ne se modifie pas : écrire une seconde fois let notes = ... crée une nouvelle liaison, qui masque l’ancienne sans la changer. Il n’existe donc aucune affectation comme somme = somme + note.let ... in donne un nom utilisable seulement dans le calcul écrit après in : let (somme, nombre) = ... in est suivi du calcul qui se sert de somme et de nombre.rec), c’est-à-dire une fonction qui s’appelle elle-même. Pour la liste [12; 7; 15], somme_et_nombre demande d’abord le résultat pour [7; 15], qui demande celui de [15], qui demande celui de la liste vide [], qui vaut (0, 0). Les résultats remontent ensuite : [15] donne (15, 1), [7; 15] donne encore (15, 1) car 7 est écarté, et [12; 7; 15] donne (27, 2).match notes with distingue deux cas, chacun introduit par une barre | : [], la liste vide, et note :: reste, une liste formée d’une première note suivie des autres. Ce second cas donne en même temps un nom à la première note (note) et aux autres (reste).(somme, nombre), comme un tuple en Python. let (somme, nombre) = ... récupère les deux valeurs d’un coup, comme somme, nombre = ... en Python.if ... then ... else ... donne toujours une valeur : (somme + note, nombre + 1) ou (somme, nombre). C’est pourquoi le else est obligatoire./. divise deux nombres à virgule, et float_of_int transforme un entier en nombre à virgule. 55 / 4 donnerait l’entier 13, et 55 /. 4 serait refusé, car 55 est un entier.somme_et_nombre reste correspond à somme_et_nombre(reste) en Python. Les parenthèses servent seulement à regrouper : (moyenne_admis notes) forme un seul argument de Printf.printf.let () = ... contient ce qui est exécuté au lancement du programme, comme le code placé en dehors des fonctions en Python. Printf.printf affiche un texte ; %g marque l’endroit où la moyenne s’insère, et \n passe à la ligne.[12; 7; 15; 9; 18; 10].ocaml exécute directement le fichier ; le compilateur ocamlopt permet aussi d’en faire un fichier exécutable. 1(defun moyenne-admis (notes)
2 (let ((somme 0)
3 (nombre 0))
4 (dolist (note notes)
5 (when (>= note 10)
6 (setf somme (+ somme note))
7 (setf nombre (+ nombre 1))))
8 (/ somme nombre)))
9
10(let ((notes '(12 7 15 9 18 10)))
11 (format t "Moyenne des notes d'au moins 10 : ~a~%"
12 (float (moyenne-admis notes))))
(+ somme note) au lieu de somme + note, et (>= note 10) au lieu de note >= 10 : c’est la notation préfixée.defun), la boucle (dolist) et la condition (when) sont elles aussi des listes : en Lisp, le code a la même forme que les données.let crée les variables somme et nombre, et setf change leur valeur : (setf somme (+ somme note)) correspond à somme = somme + note.(/ somme nombre) ne donne pas 13.75 mais la fraction exacte 55/4 : Lisp sait calculer avec des fractions. float la transforme en nombre à virgule.return.'(12 7 15 9 18 10) est une liste ; l’apostrophe indique qu’il s’agit de données, et non d’une opération à calculer.format t affiche un texte ; ~a marque l’endroit où la valeur s’insère et ~% passe à la ligne.1(defn moyenne-admis [notes]
2 (let [admis (filter (fn [note] (>= note 10)) notes)]
3 (/ (reduce + admis) (count admis))))
4
5(let [notes [12 7 15 9 18 10]]
6 (println "Moyenne des notes d'au moins 10 :"
7 (double (moyenne-admis notes))))
moyenne-admis, reçoit la liste des notes et renvoie la moyenne.count joue le même rôle que len en Python.(>= note 10), (+ somme note)). Il ajoute les crochets, qui servent à écrire les listes de paramètres ([notes]) et les vecteurs, l’équivalent des listes Python : [12 7 15 9 18 10], sans virgules.defn introduit une fonction, comme def en Python ; ses paramètres sont écrits entre crochets.(fn [note] (>= note 10)) est une fonction sans nom, écrite là où on l’utilise : elle reçoit une note et répond true si elle est supérieure ou égale à 10.filter applique ce test à chaque note et ne garde que les notes pour lesquelles il répond true : (12 15 18 10). let donne le nom admis à ce résultat, sans pouvoir le changer ensuite.(reduce + admis) additionne les notes de proche en proche : 12 + 15, puis le résultat + 18, puis + 10, ce qui donne 55. C’est l’équivalent de sum(admis).(/ 55 4) donne la fraction exacte 55/4 ; double la transforme en nombre à virgule.println affiche ses arguments séparés par une espace, puis passe à la ligne, comme print en Python.clojure traduit le programme en code intermédiaire, que la machine virtuelle exécute aussitôt (voir la section « Interpréter ou compiler », sous l’éditeur). Un programme Clojure peut donc utiliser toutes les bibliothèques écrites en Java. 1#!/bin/bash
2
3moyenne_admis() {
4 somme=0
5 nombre=0
6 for note in "$@"; do
7 if [ "$note" -ge 10 ]; then
8 somme=$((somme + note))
9 nombre=$((nombre + 1))
10 fi
11 done
12 echo "scale=2; $somme / $nombre" | bc
13}
14
15notes="12 7 15 9 18 10"
16echo "Moyenne des notes d'au moins 10 : $(moyenne_admis $notes)"
for note in ... et une condition if..sh enchaîne ces commandes.$((somme + note)) calcule une somme d’entiers.bc, une commande qui sert de calculatrice ; scale=2 lui demande deux chiffres après la virgule. Le signe | transmet à bc le texte produit par echo.somme=0, sans espace autour du signe =, pour donner une valeur à une variable, et $note pour lire la valeur de la variable note.$note par sa valeur, puis découpe le résultat en mots à chaque espace. Les guillemets ("$note", "$@") empêchent ce découpage : chaque valeur reste entière, même si elle contient une espace. À l’inverse, moyenne_admis $notes est écrit sans guillemets, pour que le texte 12 7 15 9 18 10 soit découpé en six notes.-ge signifie « supérieur ou égal ».do ... done pour la boucle, if ... fi pour la condition.$@ les désigne toutes.1CREATE TABLE notes (note INTEGER);
2INSERT INTO notes VALUES (12), (7), (15), (9), (18), (10);
3
4SELECT 'Moyenne des notes d''au moins 10 : ' || AVG(note)
5FROM notes
6WHERE note >= 10;
note >= 10.CREATE TABLE crée la table avec une colonne note, puis INSERT y ajoute six lignes.SELECT ne décrit aucune étape : elle décrit le résultat voulu. WHERE garde les lignes qui vérifient la condition, et AVG calcule leur moyenne.|| met deux textes bout à bout. À l’intérieur d’un texte, l’apostrophe est doublée (d''au) pour ne pas être confondue avec la fin du texte. 1<!DOCTYPE html>
2<html lang="fr">
3<head>
4 <meta charset="utf-8">
5 <title>Moyenne des notes</title>
6</head>
7<body>
8 <h1>Notes du trimestre</h1>
9 <ul>
10 <li>12</li>
11 <li>7</li>
12 <li>15</li>
13 <li>9</li>
14 <li>18</li>
15 <li>10</li>
16 </ul>
17 <p>Moyenne des notes d'au moins 10 : <strong>13.75</strong></p>
18</body>
19</html>
<h1> un titre, <ul> une liste, <li> un élément de liste, <p> un paragraphe, <strong> un passage mis en valeur.13.75 a été écrite à la main. Pour la calculer dans la page, il faudrait ajouter un programme en JavaScript. 1<?php
2
3function moyenne_admis(array $notes): float
4{
5 $somme = 0;
6 $nombre = 0;
7 foreach ($notes as $note) {
8 if ($note >= 10) {
9 $somme = $somme + $note;
10 $nombre = $nombre + 1;
11 }
12 }
13 return $somme / $nombre;
14}
15
16$notes = [12, 7, 15, 9, 18, 10];
17echo "Moyenne des notes d'au moins 10 : " . moyenne_admis($notes) . "\n";
$somme = 0 crée la variable, comme somme = 0.foreach ($notes as $note) parcourt directement les notes, comme for note in notes, mais le tableau est écrit avant la variable.function introduit une fonction, comme def en Python.<?php, et chaque nom de variable commence par le signe $.. colle deux textes bout à bout, comme + entre deux chaînes en Python. echo affiche un texte, comme print, mais sans passer à la ligne : il faut ajouter "\n".array (un tableau) et : float (un nombre décimal) pourraient être supprimés. Quand ils sont écrits, PHP les vérifie au moment de l’exécution, et s’arrête sur une erreur si un argument n’a pas le bon type.php exécute le programme dans un terminal. 1<!DOCTYPE html>
2<html lang="fr">
3<head>
4 <meta charset="utf-8">
5 <title>Moyenne des notes</title>
6</head>
7<body>
8 <p>Notes : <input id="notes" value="12 7 15 9 18 10"></p>
9 <button id="bouton">Calculer la moyenne</button>
10 <p id="resultat"></p>
11 <script>
12 function moyenneAdmis(notes) {
13 let somme = 0;
14 let nombre = 0;
15 for (const note of notes) {
16 if (note >= 10) {
17 somme = somme + note;
18 nombre = nombre + 1;
19 }
20 }
21 return somme / nombre;
22 }
23
24 function afficherMoyenne() {
25 const texte = document.getElementById("notes").value;
26 const notes = texte.split(" ").map(Number);
27 const resultat = document.getElementById("resultat");
28 const moyenne = moyenneAdmis(notes);
29 resultat.textContent = `Moyenne des notes d'au moins 10 : ${moyenne}`;
30 }
31
32 document.getElementById("bouton").addEventListener("click", afficherMoyenne);
33 </script>
34</body>
35</html>
moyenneAdmis est celle de la version JavaScript, elle-même très proche de la version Python.addEventListener("click", afficherMoyenne) joue le même rôle que command=afficher dans un bouton tkinter, vu dans le cours sur les interfaces graphiques : la fonction est appelée à chaque clic.addEventListener("click", afficherMoyenne), la fonction est écrite sans parenthèses : on ne l’appelle pas, on indique au navigateur laquelle appeler à chaque clic.document.getElementById("notes") désigne l’élément de la page dont l’attribut id vaut notes. On lit le texte du champ avec .value, et on écrit le résultat dans le paragraphe vide avec .textContent.texte.split(" ") découpe le texte à chaque espace, et .map(Number) convertit chaque morceau en nombre, comme [float(m) for m in texte.split(" ")] en Python.0 / 0 affiche NaN (en anglais, « pas un nombre ») : JavaScript continue là où Python s’arrêterait sur une erreur.Le processeur d’un ordinateur ne comprend pas directement le texte d’un programme : il faut le traduire en instructions du processeur. Il existe deux façons de le faire.
python3 moyenne.py : python3 est l’interpréteur de Python. JavaScript, PHP et le shell sont aussi interprétés.gcc pour le C (gcc moyenne.c -o moyenne crée le fichier exécutable moyenne, lancé par ./moyenne), g++ pour le C++ et rustc pour Rust. Go et Swift sont aussi compilés.Java, Kotlin et Clojure procèdent en deux temps. Leur compilateur (javac pour Java) ne produit pas des instructions pour le processeur de l’ordinateur, mais pour un processeur imaginaire, le même pour tous les ordinateurs : on parle de code intermédiaire. Ce code est ensuite exécuté par la machine virtuelle Java, un logiciel qui joue le rôle de ce processeur imaginaire : il lit le code intermédiaire et le fait exécuter par le vrai processeur. C’est elle que lance la commande java Moyenne. Une fois la machine virtuelle installée, le même fichier compilé fonctionne aussi bien sous Windows que sous macOS ou Linux.
TypeScript est lui aussi compilé, mais en JavaScript, et non en instructions du processeur : son compilateur tsc vérifie les types, puis écrit le fichier moyenne.js, que l’interpréteur node exécute ensuite.
D’un langage à l’autre, le programme ne change pas seulement de mots : il ne suit pas toujours la même démarche. On parle de style de programmation (ou de paradigme).
Style impératif : le programme décrit les étapes à suivre, une par une, et des variables changent de valeur pendant l’exécution (somme = somme + note). Les versions en Python, C, C++, JavaScript, TypeScript, Go, Rust, Kotlin, Swift, Lisp et PHP suivent ce style.
Style orienté objet (ou style objet) : le programme est organisé en classes, qui regroupent des données et les fonctions qui agissent sur ces données. En Java, tout programme est rangé dans une classe. Ce style est étudié en terminale.
Style fonctionnel : le programme est construit en combinant des fonctions, sans aucune variable qui change de valeur. Les versions en Haskell et en Clojure utilisent une fonction qui filtre la liste ; la version en OCaml utilise une fonction récursive, c’est-à-dire une fonction qui s’appelle elle-même. La récursivité est étudiée en terminale.
En style fonctionnel, le mot variable garde le sens qu’il a en mathématiques : dans f(x) = 2x + 1, la variable x prend une valeur différente à chaque calcul de f, mais ne change pas pendant ce calcul. Le paramètre notes de la version OCaml est une variable de ce type : il désigne une autre liste à chaque appel, mais rien ne peut le modifier pendant le calcul.
Style événementiel : le programme associe des fonctions à des événements (un clic, une touche, le chargement d’une page), puis attend ; chaque fonction est appelée quand son événement se produit. C’est le style des interfaces graphiques, déjà rencontré avec tkinter dans le cours sur les interfaces graphiques, et des pages web : le dernier onglet en donne un exemple.
Beaucoup de langages permettent plusieurs styles : on peut aussi écrire des classes en Python, en C++, en Kotlin ou en Swift, et Python possède lui aussi une fonction filter. Lisp, l’un des tout premiers langages, permet le style impératif comme le style fonctionnel, qu’il a contribué à inventer. Clojure, un langage récent de la même famille, encourage le style fonctionnel : la version en Lisp utilise une boucle, celle en Clojure n’en utilise aucune.
Il existe d’autres styles. En programmation logique, par exemple avec le langage Prolog, on décrit des faits et des règles, puis on pose une question : le langage cherche lui-même les réponses qui respectent ces règles.
Le shell est un langage de commandes : un fichier écrit en shell enchaîne les commandes que l’on pourrait taper une à une dans un terminal.
Deux onglets ne montrent pas des langages de programmation :
Pour chaque langage, le tableau montre comment s’écrivent l’affectation, la condition et la boucle, comment sont délimités les blocs (le corps d’une boucle, d’une condition ou d’une fonction), et si les types des variables sont écrits dans le code.
Un type non écrit n’est pas pour autant absent : en TypeScript, Go, Rust, Kotlin, Swift, Haskell et OCaml, le compilateur le déduit et le vérifie avant l’exécution, et une variable ne peut jamais changer de type. En Python, en JavaScript, en Lisp, en Clojure et en shell, le type d’une valeur n’est connu qu’au moment de l’exécution. En PHP aussi : même quand les types sont écrits, ils ne sont vérifiés que pendant l’exécution.
| Langage | Affectation | Condition | Boucle | Blocs | Types écrits |
|---|---|---|---|---|---|
| Python | somme = 0 |
if note >= 10: |
for note in notes: |
indentation | non |
| C | int somme = 0; |
if (notes[i] >= 10) |
for (int i = 0; i < taille; i++) |
{ } |
oui |
| C++ | int somme = 0; |
if (note >= 10) |
for (int note : notes) |
{ } |
oui |
| JavaScript | let somme = 0; |
if (note >= 10) |
for (const note of notes) |
{ } |
non |
| TypeScript | let somme = 0; |
if (note >= 10) |
for (const note of notes) |
{ } |
pour les paramètres et le résultat |
| Langage | Affectation | Condition | Boucle | Blocs | Types écrits |
|---|---|---|---|---|---|
| Java | int somme = 0; |
if (note >= 10) |
for (int note : notes) |
{ } |
oui |
| Go | somme := 0 |
if note >= 10 |
for _, note := range notes |
{ } |
pour les paramètres et le résultat |
| Rust | let mut somme = 0; |
if note >= 10 |
for ¬e in notes |
{ } |
pour les paramètres et le résultat |
| Kotlin | var somme = 0 |
if (note >= 10) |
for (note in notes) |
{ } |
pour les paramètres et le résultat |
| Langage | Affectation | Condition | Boucle | Blocs | Types écrits |
|---|---|---|---|---|---|
| Swift | var somme = 0 |
if note >= 10 |
for note in notes |
{ } |
pour les paramètres et le résultat |
| Haskell | aucune variable modifiée | filter (>= 10) notes |
aucune boucle | indentation | facultatifs (écrits ici) |
| OCaml | aucune variable modifiée | if note >= 10 then |
aucune boucle (fonction récursive) | let ... in |
non |
| Lisp | (let ((somme 0)) ...) |
(when (>= note 10) ...) |
(dolist (note notes) ...) |
parenthèses | non |
| Langage | Affectation | Condition | Boucle | Blocs | Types écrits |
|---|---|---|---|---|---|
| Clojure | aucune variable modifiée | (filter (fn [note] (>= note 10)) notes) |
aucune boucle | parenthèses | non |
| Shell | somme=0 |
if [ "$note" -ge 10 ] |
for note in "$@" |
do ... done |
non |
| SQL | aucune | WHERE note >= 10 |
aucune boucle | aucun | dans la table |
| HTML | aucune | aucune | aucune boucle | balises | non |
| PHP | $somme = 0; |
if ($note >= 10) |
foreach ($notes as $note) |
{ } |
facultatifs (écrits ici) |
Aucun langage ne convient à tout : chacun a été conçu pour un usage, et on le choisit selon le besoin (une page web, une application de téléphone, un calcul qui doit être rapide, une base de données). Le tableau indique dans quel domaine chaque langage est le plus utilisé, ce qu’il apporte par rapport aux autres et ses principales limites.
| Langage | Domaines d’utilisation | Atouts | Limites |
|---|---|---|---|
| Python | enseignement, analyse de données, intelligence artificielle, petits programmes qui automatisent des tâches | syntaxe lisible et courte ; nombreuses bibliothèques pour le calcul, les graphiques et l’intelligence artificielle | exécution plus lente que celle d’un programme compilé ; erreurs de type découvertes seulement à l’exécution |
| C | systèmes d’exploitation (Linux), objets connectés, interpréteurs (celui de Python est écrit en C) | programmes très rapides ; compilateurs disponibles pour presque tous les processeurs | le programmeur gère lui-même la mémoire, ce qui provoque des erreurs et des failles de sécurité |
| Langage | Domaines d’utilisation | Atouts | Limites |
|---|---|---|---|
| C++ | jeux vidéo, navigateurs web, logiciels de calcul | la rapidité du C, avec en plus les classes et une large bibliothèque standard | langage vaste et long à maîtriser ; mêmes risques liés à la mémoire qu’en C |
| JavaScript | pages web, dans le navigateur ; serveurs, avec Node.js | le langage de programmation des pages web : tous les navigateurs l’exécutent, sans rien installer | conversions de types surprenantes : "5" + 1 vaut "51" |
| TypeScript | applications web de grande taille | les types, vérifiés avant l’exécution, détectent beaucoup d’erreurs | une étape de compilation en plus ; les types ne sont plus vérifiés pendant l’exécution |
| Langage | Domaines d’utilisation | Atouts | Limites |
|---|---|---|---|
| Java | logiciels d’entreprise, serveurs, applications Android | le même fichier compilé fonctionne sur tous les systèmes, grâce à la machine virtuelle | code long à écrire : classes obligatoires et types écrits partout |
| Go | serveurs et services en ligne, outils d’hébergement (Docker est écrit en Go) | compilation rapide, programmes rapides ; plusieurs tâches menées en même temps facilement | langage volontairement réduit : moins de constructions que Python |
| Rust | logiciels où la sécurité compte : navigateurs, systèmes d’exploitation | aussi rapide que le C, mais le compilateur refuse les programmes qui utilisent mal la mémoire | apprentissage difficile : le compilateur refuse beaucoup de programmes |
| Langage | Domaines d’utilisation | Atouts | Limites |
|---|---|---|---|
| Kotlin | applications Android, recommandé par Google depuis 2019 | plus court à écrire que Java, et compatible avec les programmes Java | dépend de la machine virtuelle et des outils de Java |
| Swift | applications pour iPhone, iPad et Mac | rapide, et plus sûr que les langages qu’Apple utilisait avant lui | presque uniquement utilisé sur les appareils Apple |
| Haskell | recherche, quelques entreprises de la finance | style fonctionnel strict ; types très précis, vérifiés avant l’exécution | peu répandu dans les entreprises ; demande une autre façon de penser |
| Langage | Domaines d’utilisation | Atouts | Limites |
|---|---|---|---|
| OCaml | outils qui vérifient d’autres programmes, compilateurs, enseignement en classes préparatoires | types déduits et vérifiés avant l’exécution ; programmes rapides | communauté réduite, donc moins de bibliothèques |
| Lisp | intelligence artificielle des débuts, programmes qui étendent un logiciel (l’éditeur Emacs) | un programme Lisp est lui-même une liste, qu’un autre programme peut lire et transformer | nombreuses parenthèses ; peu utilisé aujourd’hui |
| Clojure | serveurs et services en ligne, traitement de données (la banque Nubank l’utilise pour ses services) | style fonctionnel ; des données qui ne se modifient jamais, donc moins d’erreurs quand plusieurs tâches s’exécutent en même temps ; accès à toutes les bibliothèques Java | démarrage lent, dû à la machine virtuelle Java ; messages d’erreur difficiles à lire |
| Langage | Domaines d’utilisation | Atouts | Limites |
|---|---|---|---|
| Shell | automatisation des tâches d’un ordinateur, administration des serveurs | enchaîne directement les commandes du terminal | mal adapté aux calculs et aux longs programmes ; règles pièges sur les espaces et les guillemets |
| SQL | bases de données des sites web, des banques, des administrations | on décrit le résultat voulu, et le logiciel de la base trouve lui-même comment l’obtenir | sert seulement à interroger et à modifier des bases de données |
| HTML | contenu des pages web | lu par tous les navigateurs | ne calcule rien ; l’apparence de la page est décrite à part, en CSS |
| PHP | sites web, côté serveur (Wikipédia et WordPress sont écrits en PHP) | conçu pour fabriquer des pages web ; proposé par presque tous les hébergeurs | des noms de fonctions peu réguliers, hérités de ses débuts |