# Programmer en R/Programmation procédurale

Le langage R permet de faire de la programmation procédurale, ce qui donne accès à la mise en œuvre d'algorithmes complexes.

## Structure générale d'un programme

Un programme est une suite d'instructions, qui peuvent être séparées par un point-virgule « ; » ou par une fin de ligne. Un point-virgule indique toujours la fin d'une instruction, alors qu'une fin de ligne est ignorée si la syntaxe de l'instruction n'est pas complète.
Les instructions peuvent être regroupées en blocs délimités par une paire d'accolades « {…} ».
Une instruction est évaluée lorsque sa syntaxe est complète et que l'on introduit une fin de ligne ; le programme R renvoie alors la valeur issue de l'évaluation de l'instruction. Un bloc est interprété comme une instruction, c'est-à-dire qu'il n'est évalué qu'à la fin de ligne suivant l'accolade fermante.
Un commentaire est introduit par le croisillon #.

## Interactions avec l'utilisateur

On peut afficher des messages avec la commande print("Message").
Pour permettre à l'utilisateur de saisir une valeur, on utilise la commande scan, sous la forme
La fonction construit un vecteur : lorsque l'on appuie sur la touche [Entrée], il demande la valeur suivante. Pour terminer la saisie, on entre une valeur vide.
Par défaut, R considère que c'est une chaîne de caractères. On peut utiliser l'option what pour forcer un autre type :
* what = numeric : nombre réel ;
* what = integer : nombre entier ;
* what = double : nombre réel à double précision ;
* what = logical : booléen TRUE (ou T) et FALSE (ou F).
Par exemple
On peut aussi avoir un éditeur de type tableur avec la commande data.entry :
Il faut entrer les données dans la première colonne « a ». Il faut cliquer sur l'en-tête de la colonne pour définir si l'on veut entrer des nombres (numeric) ou des caractères (character). La variable est enregistrée lorsque l'on ferme la fenêtre du tableur.

## Structures de contrôle
### Évaluation conditionnelle

L'évaluation conditionnelle d'une instruction se fait avec la structure
où l'évaluation de instruction1 doit être un booléen :
* instruction2 est évalué si instruction1 est vrai ;
* instruction3 est évalué si instruction1 est faux.
La structure ci-dessus forme un bloc ; ainsi, on peut l'évaluer, et mettre la valeur dans une variable. Par exemple, les deux programmes ci-dessous sont équivalents :
et
Si l'on veut écrire la structure sur plusieurs lignes, il faut la mettre dans un bloc :
ou bien utiliser, pour instruction2, un bloc se fermant avant le else :
On peut enchaîner les évaluations conditionnelles avec l'instruction elsif.

### Évaluation à choix multiple

La structure switch permet de faire des choix multiples (l'équivalent de la structure case d'autres langages). La syntaxe générale est :
où liste est une suite d'instructions séparées par une virgule.
Si l'évaluation de l'instruction est un nombre entier n, alors l'interpréteur exécute la n-ième instruction de la liste. Par exemple
renvoie "e".
Si l'évaluation de l'instruction est une chaîne de caractères, alors la liste doit être une succession d'instructions de type nom = valeur. Si l'évaluation de l'instruction correspond exactement à un nom de la liste, alors l'évaluation de la structure renvoie la valeur correspondante. La liste peut contenir une valeur sans nom qui sert de valeur par défaut.
Par exemple
renvoie "banane" ; avec plat <- "viande", l'évaluation renvoie "aucun". Notons que la valeur peut être quelconque : scalaire, vecteur, instruction, …

## Tri, recherche et sélection

L'instruction sort permet de classer des vecteurs. Par exemple, le code suivant classe par ordre croissant :
Pour classer par ordre décroissant, on ajoute l'option decreasing = TRUE :
On peut indiquer l'algorithme de tri utilisé : method = "shell" (cas général) pour la méthode de Shell (cas général), ou bien method = "quick" pour le tri rapide (uniquement pour les valeurs numériques).
On peut aussi ne classer que certaines valeurs : on utilise l'option partial = vecteur où vecteur est un vecteur d'indices. Le tri n'est alors pas complet, mais on est sûr que pour chaque élément désigné de la liste triée, les éléments précédents ont une valeur inférieure, et les éléments suivants ont une valeur supérieure. Cela permet d'avoir un résultat plus rapidement. Par exemple, si l'on veut connaître la valeur de la médiane, il suffit de classer l'élément médian :
Le résultat peut être différent de median(x) si le nombre d'éléments est pair. Le script suivant donne la valeur conventionnelle de la médiane, et la compare avec l'évaluation de la fonction median.
L'instruction rank donne l'ordre des éléments d'un vecteur :
si x est un vecteur de n éléments, alors y est un vecteur de n nombres entiers (ou éventuellement fractionnaire si certaines valeur de x sont en double) ; y(i) est le rang de la valeur x(i) dans la liste x triée.
indique que la valeur « 1 » est la 1re, la valeur « 3 » est la 3e, la valeur « 2 » est la 2e et la valeur « 5 » est la 4e de la liste triée. En cas de doublons (ties), on peut préciser la méthode de classement :
* ties.method = "average" attribue à chaque élément la moyenne des rangs ; dans l'exemple suivant, on a trois fois la valeur « 1 », donc cette valeur a trois rangs (1, 2, 3) dont la moyenne vaut (1 + 2 + 3)/ = 2 ;
* ties.method = "first" incrémente le rang à chaque occurrence de la valeur, soit dans notre exemple 1, 2 puis 3 ;
* ties.method = "min" attribue à chaque élément le premier rang rencontré (ici, 1, soit trois premiers ex aequo) ; c'est typiquement la méthode du classement sportif ;
* ties.method = "max" attribue à chaque élément le dernier rang rencontré ; dans l'analyse de survie et de fiabilité, la fréquence cumulée par la méthode des modes est obtenue en prenant ce rang-là divisé par la taille de l'échantillon ;
* ties.method = "random" est identique à <code"first" mais les rangs sont distribués aléatoirement à chaque valeur.
L'instruction order permet de classer des matrices et data frames.
La recherche se fait avec une paire de double-crochet : l'expression
renvoie l'indice de la première occurrence de la valeur a dans le vecteur ou la matrice 'x. Si x est une matrice, i est un indice unique, obtenu en parcourant la matrice colonne par colonne, de haut en bas et de gauche à droite. Par exemple :
Si l'on veut trouver toutes les occurrences d'une valeur, on utilise la fonction which :
Cette commande fonctionne avec toute matrice booléenne, par exemple
On peut aussi utiliser directement une matrice booléenne pour extraire des éléments :

## Lecture et enregistrement de données

La commande scan permet d'aller lire les valeurs dans un fichier texte. Si par exemple les données sont dans le fichier valeurs.txt sous la forme :
(une donnée par ligne), il faut entrer
mais si elles sont sous la forme
il faut indiquer que le séparateur est la virgule
Si l'on indique un chemin d'accès (répertoire, dossier), il faut utiliser la barre oblique (slash) / même sous Microsoft Windows, par exemple
Si l'on a un fichier au format CSV (comma separated values), par exemple exporté depuis un tableur, on peut utiliser la commande

## Bonnes pratiques de programmation

Nous rappelons ci-dessous quelques règles de bonne pratique. Ces règles sont destinées à réduire le risque d'erreur. En particulier, une autre personne que le programmeur doit pouvoir lire le code et le comprendre, et le programmeur doit être capable de se relire plusieurs mois ou années après avoir écrit son code. Cela permet le déverminage (débogage, recherche et correction des erreurs) et l'évolution du programme.
Le code doit être le plus général possible, ce qui permet sa transposition à d'autres applications (copier-coller). En particulier, on évite les valeurs numériques « en dur », on définit à la place des constantes en début de programme.
Le code doit être fractionné : il comprend typiquement trois grandes parties :
* Initialisation et définition des constantes.
* Définition des fonctions.
* Programme principal.
Le programme principal doit être très court, et consister essentiellement à des appels de fonctions.
Une fonction ne doit pas faire plus d'une page de long (25 lignes), et ne doit pas contenir plus d'une dizaine de variables locales ; si ce n'est pas le cas, c'est qu'elle peut probablement être divisée en plusieurs fonctions. En particulier, chaque fois qu'une portion de code est dupliquée, elle doit être remplacée par une fonction.
Et une ligne ne doit pas faire plus de la largeur d'une page (80 caractères), et ne doit contenir qu'une seule instruction.
Le code doit être indenté : des blancs en début de ligne marquent l'imbrication des commandes, en particulier à l'intérieur d'un bloc délimitant une fonction (function {…}), de boucles (for, while, repeat) et des exécutions conditionnelles (if … else …).
Le code doit être abondamment commenté. En particulier, pour chaque fonction, on indique
* à quoi elle sert (son but, son objectif, sa fonctionnalité) ;
* quelles sont les données d'entrée (arguments), et en particulier leur format (réel, complexe, booléen, chaîne de caractères) ;
* quelles sont les données de sortie (idem).
Les grandes étapes de la fonction doivent être expliquées.

## Exemples
### Courbe de von Koch

Le programme suivant trace la courbe du flocon de Koch de manière récursive.