1 Entrées/sorties en Ocaml

Documents pareils
Classes et Objets en Ocaml.

Algorithmique et Programmation, IMA

modules & compilation

Programmation système I Les entrées/sorties

# let rec concat l1 l2 = match l1 with [] -> l2 x::l 1 -> x::(concat l 1 l2);; val concat : a list -> a list -> a list = <fun>

Introduction à la programmation Travaux pratiques: séance d introduction INFO0201-1

TP 1. Prise en main du langage Python

TP1 : Initiation à Java et Eclipse

Exceptions. 1 Entrées/sorties. Objectif. Manipuler les exceptions ;

Le langage C. Séance n 4

Utilisation d objets : String et ArrayList

TP3 : Manipulation et implantation de systèmes de fichiers 1

Les chaînes de caractères

Conventions d écriture et outils de mise au point

Cours 1 : La compilation

Java Licence Professionnelle CISII,

TP n 2 Concepts de la programmation Objets Master 1 mention IL, semestre 2 Le type Abstrait Pile

Cours de Programmation 2

Bases de programmation. Cours 5. Structurer les données

STAGE IREM 0- Premiers pas en Python

Info0101 Intro. à l'algorithmique et à la programmation. Cours 3. Le langage Java

Éléments d informatique Cours 3 La programmation structurée en langage C L instruction de contrôle if

TP1 - Prise en main de l environnement Unix.

length : A N add : Z Z Z (n 1, n 2 ) n 1 + n 2

Cours d Algorithmique-Programmation 2 e partie (IAP2): programmation 24 octobre 2007impérative 1 / 44 et. structures de données simples

Rappels Entrées -Sorties

Les structures. Chapitre 3

IN Cours 1. 1 Informatique, calculateurs. 2 Un premier programme en C

INITIATION AU LANGAGE C SUR PIC DE MICROSHIP

Introduction au langage C

Langage et Concepts de ProgrammationOrientée-Objet 1 / 40

OCL - Object Constraint Language

ACTIVITÉ DE PROGRAMMATION

1) Installation de Dev-C++ Téléchargez le fichier devcpp4990setup.exe dans un répertoire de votre PC, puis double-cliquez dessus :

Présentation du langage et premières fonctions

Cours 1 : Introduction. Langages objets. but du module. contrôle des connaissances. Pourquoi Java? présentation du module. Présentation de Java

Programmation C++ (débutant)/instructions for, while et do...while

1/24. I passer d un problème exprimé en français à la réalisation d un. I expressions arithmétiques. I structures de contrôle (tests, boucles)

Recherche dans un tableau

Traduction des Langages : Le Compilateur Micro Java

Premiers Pas en Programmation Objet : les Classes et les Objets

Structure d un programme et Compilation Notions de classe et d objet Syntaxe

Chap III : Les tableaux

Programme Compte bancaire (code)

Langage Java. Classe de première SI

Initiation à l algorithmique

Le Langage C Version 1.2 c 2002 Florence HENRY Observatoire de Paris Université de Versailles florence.henry@obspm.fr

Vérification de programmes et de preuves Première partie. décrire des algorithmes

Suivant les langages de programmation, modules plus avancés : modules imbriqués modules paramétrés par des modules (foncteurs)

Cours intensif Java. 1er cours: de C à Java. Enrica DUCHI LIAFA, Paris 7. Septembre Enrica.Duchi@liafa.jussieu.fr

Cours d initiation à la programmation en C++ Johann Cuenin

TP1 : Initiation à Java et Eclipse

Initiation à la Programmation en Logique avec SISCtus Prolog

Programmation impérative

Compléments de documentation Scilab : affichage de texte et formatage de nombres

Correction Code nécessaire à la compilation : let bs ="\\" let nl = "\n" ;; let appliquer = List.map ;; (* affichage d'un noeud *)

Découverte de Python

Introduction à MATLAB R

EPREUVE OPTIONNELLE d INFORMATIQUE CORRIGE

Gestion mémoire et Représentation intermédiaire

Programmation Web. Madalina Croitoru IUT Montpellier

Perl Console. Votre compagnon pour développer en Perl. Les Journées du Perl , 17 novembre, Lyon. Alexis Sukrieh

Cours Informatique Master STEP

Programmer en JAVA. par Tama

Travaux pratiques. Compression en codage de Huffman Organisation d un projet de programmation

Rappel. Analyse de Données Structurées - Cours 12. Un langage avec des déclaration locales. Exemple d'un programme

Pour signifier qu'une classe fille hérite d'une classe mère, on utilise le mot clé extends class fille extends mère

Machines virtuelles fonctionnelles (suite) Compilation ML Java

Table des matières PRESENTATION DU LANGAGE DS2 ET DE SES APPLICATIONS. Introduction

TD3: tableaux avancées, première classe et chaînes

TP, première séquence d exercices.


«Dire et écrire» pour réaliser une composition en travail collaboratif en géographie. Agnès Dullin, lycée J. Racine 20 rue du Rocher, Paris

Licence Bio Informatique Année Premiers pas. Exercice 1 Hello World parce qu il faut bien commencer par quelque chose...

SNT4U16 - Initiation à la programmation TD - Dynamique de POP III - Fichiers sources

Outils pour la pratique

Cours 1 : Qu est-ce que la programmation?

Le prototype de la fonction main()

Introduction à l algorithmique et à la programmation M1102 CM n 3

Algorithmique & programmation

Notions fondamentales du langage C# Version 1.0

Application 1- VBA : Test de comportements d'investissements

La mémoire. Un ordinateur. L'octet. Le bit

1 Lecture de fichiers

Algorithmique et programmation : les bases (VBA) Corrigé

2 Comment fonctionne un ordinateur, dans les grandes lignes

Langage et Concepts de Programmation Objet. 1 Attributs et Méthodes d instance ou de classe. Travaux Dirigés no2

ET 24 : Modèle de comportement d un système Boucles de programmation avec Labview.

Les fichiers. Chapitre 4

Plan. Exemple: Application bancaire. Introduction. OCL Object Constraint Language Le langage de contraintes d'uml

Plan du cours. Historique du langage Nouveautés de Java 7

1 Introduction - Qu est-ce que le logiciel R?

3. SPÉCIFICATIONS DU LOGICIEL. de l'expression des besoins à la conception. Spécifications fonctionnelles Analyse fonctionnelle et méthodes

Expression des contraintes. OCL : Object C o n t r a i n t L a n g u a g e

Programmation VBA/Excel. Programmation VBA. Pierre BONNET. Masters SMaRT & GSI - Supervision Industrielle P. Bonnet

SCL LOGICIEL DE CONTROL

Programmation C. Apprendre à développer des programmes simples dans le langage C

Présentation du PL/SQL

RAPPELS SUR LES METHODES HERITEES DE LA CLASSE RACINE Object ET LEUR SPECIALISATION (i.e. REDEFINITION)

Transcription:

L objectif de cet exercice était de vous faire manipuler des tableaux, et notamment d observer les différences entre les tableaux et les listes. Cependant, l exercice contenait quelques pièges et je dois admettre qu il est un peu difficile pour un premier exercice. J ai notamment oublié de vous parler des fonctions d entrées/sorties afin que vous puissiez tester vos fonctions. 1 Entrées/sorties en Ocaml Contrairement à l interpréteur, lorsque vous écrivez un programme en Ocaml puis que vous le compilez, afin de voir quelque chose sur la console, il vous faut écrire une fonction qui affiche explicitement quelque chose à l écran. La sortie standard est un terme pour désigner ce vers quoi vous voulez afficher. En Ocaml, la variable qui permet d afficher sur la sortie standard s appelle stdout (comme standard output. Lorsque vous lancez votre programme depuis le terminal, la sortie standard correspond au terminal. Donc afficher du texte sur la sortie standard revient à écrire du texte dans le terminal. De façon symmétrique, on parle d entrée standard pour parler de ce que votre programme peut récupérer en entrée depuis l extérieur. Èvidemment, l éxtérieur peut désigner beaucoup de chose, même si dans notre cas ce sera principalement des valeurs saisies au clavier depuis le terminal. Vous verrez dans le cours d Architectures et systèmes d autres façon de récupérer des valeurs du monde extérieur. Le module qui permet d afficher du texte en Ocaml s appelle Printf. C est celui que nous avons utilisé lorsqu on a affiché notre premier texte : hello world. La fonction que l on a utilisé s appelle aussi printf. Notez bien la différence entre le nom de module qui commence par une majuscule et celui de la fonction qui commence par une minuscule. 1 Le module Printf déclare plusieurs fonctions dans le but est toujours le même : afficher du texte! Dans notre cas, les fonctions qui nous intéressent sont fprintf, printf et sprintf. Les deux dernières étant des cas particuliers de la première. Avec fprintf vous pouvez choisir le channel de sortie. On a vu qu il existait un channel particulier qui s appelle la sortie standard, mais il en existe d autre, par exemple la sortie d erreur (stderr). printf est un cas particulier de fprintf où le channel est stdout. sprintf est un autre cas particulier où le channel est finalement une autre chaîne de caractère. Ainsi, les trois instructions suivantes produisent la même chose : let _ = Printf.fprintf stdout ``Hello world!\n'' let _ = Printf.printf ``Hello world!\n'' 1 D ailleurs il y a une différence sémantique entre les noms qui commencent par une majuscule et ceux qui commencent par une minuscules. Vos noms de variables/fonctions (même si sensiblement la même chose en Ocaml) doivent toujours commencer par une miniscule. Les noms commençant par une majuscule sont réservés pour les constructeurs de type ainsi que pour les noms de module 1

let _ = Printf.printf ``%s" (Printf.sprintf ``Hello world!\n") Le dernier exemple introduit la fonctionnalité majeur des fonctions d affichage d Ocaml que sont les format. Si vous regardez le type de printf dans la doc, vous pouvez voir que son type est : val printf : ('a, out_channel, unit) format -> 'a Les formats sont des types hautement polymorphes. Cependant pour le moment, on considerera que les formats ne sont ni plus ni moins des chaînes de caractères dans lesquelles ont peut rajouter des arguments sous forme de format justement. Un format commence toujours par le symbole % et est suivi d une lettre, cette dernière indiquant le type de l argument attendu. Dans l exemple avec sprintf, la lettre qui suit le % est un s ce qui veut dire que l argument attendu est de type string. Les différents formats possibles sont décrit dans la documentation du module Printf mais voici les plus utiles : %d pour un entier %s pour une chaîne %f pour un nombre floattant %b pour un booléen Le truc chouette avec les format, c est qu on peut les enchaîner. Ainsi, on peut écrire let _ = Printf.printf ``%d + %d <> %f" 42 42 85 Notez bien qu après la chaîne de caractère formatée, il y a autant d argument que de format dans la chaîne. Les saisies utilisateur fonctionnent de façon similaire sauf que l argument attendu est une fonction qui qui est appliquée à la valeur lue. Ces fonctions se trouvent dans le module Scanf. Par exemple let _ = Scanf.scanf ``%d'' (fun x -> Printf.printf ``%d'' x) affiche l entier entrée par l utilisateur. 2 Afficher vos types Un des problèmes qui a été soulevé lors de cette séance, c est comment afficher un tableau? Les formats ne sont utilisés que pour les types simples (int, bool, string,...). Si vous voulez afficher des objets plus compliqués comme des listes ou des tableaux, c est à vous de le faire! Pour cela, un des idiomes du langage c est de créer des fonctions 2

val string_of_mytype : mytype -> string Ensuite pour afficher un objet de votre type vous pouvez faire let _ = Printf.printf ``%s\n" (string_of_mytype myobject) Dans notre cas, ce qui nous intéressait, c était de créer une fonction string of array. Certains parmi vous ont tenté une implémentation qui donnait à la fonction string of array le type : val string_of_array : int array -> string ce qui veut dire que votre fonction ne fonctionne que pour des tableaux d entiers. Or, c est plutôt problématique puisque les tableaux étant un type polymorphe, on voudrait pouvoir réutiliser notre fonction pour différent type de tableaux. Pour cela on a pas le choix, il faut que la fonction prenne un autre argument en entrée qui dise comment afficher des éléments de type α. Le type de string of array devient alors val string_of_array : ('a -> string) -> 'a array -> string Une implémentation possible pour string of array est la suivante : let string_of_array f a = let (pre,sep,post) = ("[ ",","," ]") in let s = Array.fold_left (fun s e -> s^(f e)^sep) pre a in let s' = if Array.length a <> 0 then String.sub s 0 (String.length s - 1) else s in s'^post 3 Correction de l exercice 1 3.1 Question 1 La première question vous demandait d implémenter une fonction array of list de type val array_of_list : 'a list -> 'a arrow qui convertissait une liste en un tableau. Cette première question comportait un premier piège à savoir, que se passe-t-il si ma liste est vide? Vous voulez retournez un tableau vide qui soit polymorphe. Or, la fonction make proposée par la librairie standard ne vous propose pas de créer un tel tableau. En effet, le type de l expression 3

Array.make 0 0 est int array. D ailleurs, vous pouvez tester let _ = Printf.printf "%b\n" (Array.make 0 0 = Array.make 0 "") mais le booléen retourné par Ocaml est false. Pour cela, je rajoutais une indication dans le TP qui vous indiquait de façon un peu magique que la syntaxe [ ] construit un tableau vide polymorphe. Le problème étant reglé pour la liste vide, il reste à traiter le cas récursif. Cette fois, sachant que la liste n est pas vide, on peut initialisé le tableau avec le premier élément de la liste. Voici un exemple d implémentation d array of list: let array_of_list l = match l with [] -> [ ] x::t -> let a = Array.make (List.length l) x in let rec fill i l = match l with [] -> a x::t -> Array.set a i x; fill (i+1) t in fill 1 t ce qui peut aussi s écrire en utilisant la fonction iteri du module List : let array_of_list l = match l with [] -> [ ] x::t -> let a = Array.make (List.length l) x in List.iteri (fun i e -> a.(i) <- e) l; a Cette version utilise de la récursivité. Je vous laisse le soin de le refaire avec une boucle for par exemple. 3.2 Question 3 Fort heureusement, il se trouve que cette question est beaucoup plus simple que la précédente. Pour ma part, j ai opté pour une solution utilisant fold left : let list_of_array a = Array.fold_left (fun l x -> x::l) [] a 4

3.3 Question 5 & Question 6 La question 5 de prime abord ne semble pas très compliqué. Il suffit de créer un tableau dont tous les éléments seront eux aussi des tableaux. Cela peut se faire ainsi : let make_matrix n m = Array.make n (Array.make m 0) Mais si vous faites la question 6, vous allez vous rendre compte que cette solution ne fonctionne pas. En effet, créons une matrice de taille 4 4 et affichons-là : let m = make_matrix 4 4 let _ = m.(2).(1) <- 1 let _ = Printf.printf "%s\n" (string_of_array (string_of_array string_of_int) m) Le résultat affiché par la console est : [ [ 0,1,0,0 ],[ 0,1,0,0 ],[ 0,1,0,0 ],[ 0,1,0,0 ] ] C est un peu décevant n est-ce pas? Le soucis vient du fait que le tableau Array.make m 0 se retrouve dupliqué. L explication de ce phénomène, vous le comprendrez plus aisément lors des TP de C que vous ferez avec Lucca. Grossomodo, contrairement à une liste, un tableau est assigné à une adresse particulière de la mémoire ce qui fait que la fonction make matrix ci-dessus est équivalente à let make_matrix n m = let tmp = Array.make m 0 in Array.make n tmp Ca veut dire que le tableau extérieur est initialisé n fois avec la même adresse qui contient un tableau de taille m initialisé à 0. Le schéma de gauche de la figure 1 montre ce qui se passe réellement en mémoire. Les flèches sont des pointeurs : chaque case du tableau extérieur contient une adresse. La flèche montre à quoi correspond cette adresse. Pour éviter ce problème, il faut tricher un peu de telle sorte à ce qu Ocaml génère des adresse différentes à chaque fois. Pour cela, il faut se débrouiller pour que Array.make m 0 soit réévalué pour chaque case du tableau. Heureusement, une fonction de la librairie standard va nous sauver : la fonction init. Cette fonction est similaire a make sauf qu on peut paramétriser la valeur par défaut par un indice. Ainsi une correction consiste à faire let make_matrix n m = Array.init n (fun _ -> Array.make m 0) 5

Figure 1: représentation mémoire des tableaux Le schéma de droite montrent la représentation mémoire du tableau obtenu. Pourquoi ça fonctionne cette fois? Cela se repose sur le fait que même lorsqu une fonction (ici fun -> Array.make m 0) est passée en argument d une autre fonction, le corps de cette fonction (Array.make m 0) n est pas évalué directement. Il sera évalué seulement lorsque la fonction sera appliquée a un argument. Comme la fonction est appelé n fois avec les indices 0, 1,..., n 1, son corps est aussi évalué n fois. Et donc n adresse différentes sont générées. Ce phénomène arrive tout le temps lorsque l on fait de la programmation impérative, ce qui est typiquement le cas avec les array d Ocaml. Avec les listes, vous n aurez jamais ce genre de problème. 6