Licence 3, semestre 5, 2013–2014 Programmation Fonctionnelle TD1 1 Expressions, sous-expressions et règles de portée Entourer toutes les sous-expressions (et sous-sous-expressions) des expressions suivantes. Vérifier également le respect des règles de portée. Si la déclaration est typable, donner son type et sa valeur. Chaque ligne correspond à une ligne du top-level. 1. let x = 1 in x + 1 2. let x = 3 let x = 1 in x + 1 let y = x + 2 3. let x = 1 in let y = 2 in let x = 3 in x + y 4. let x = 3 let x = 1 in let y = x + 2 in x + y 5. let x = 3 let x = let y = 4 in y + 1 in x + y 6. let x = let y = 1 in x + y in x * 2 7. let x = 1 in let y = let x = 2 in x in y + x 8. let x = if true then let y = 2 in y + 1 else 5 9. let x = if true then let tmp = 5.0 in 0.0 else tmp /. 2.0 10. let () = if c then print int 1; print int 3 11. let x = if true then print int 1; 3 else 5 2 Fonctions Donner le type des fonctions suivantes ou expliquer pourquoi elles ne sont pas typables. 1 1. let f x = x *. 2. /. 4 2. let f x y = let x = float (x + 3) in Printf.printf "valeur %s : %f\n" y x 3. let f x y = let g x y = float x +. y in g y x 4. let f let let g x x g h + = x = x + 1 in x = x +. 2. in h x 5. let f x = let g y = y + int_of_string x in let x = 12 in g 4 6. let f x = let g y = y +. float x in let x = 12 + x in g x 3 Programmation : drag and drop 3.1 Échauffements Le but de cette partie est de se familiariser avec les types et les fonctions données en annexes. Écrire une fonction val echauffement : unit -> unit qui effectue les étapes suivantes : 1. Lancer une fenêtre graphique de taille 300 × 300, 2. Attendre qu’une touche du clavier soit tapée, 3. Afficher le caractère de la touche et la position du curseur de la souris à ce moment là sur le terminal. Maintenant, on va programmer une petite application pour déplacer un disque de couleur à l’aide de la souris, selon le principe du drag and drop : on clique sur le disque pour le sélectionner, on le déplace avec la souris tant que le bouton est pressé, puis on le “repose” en relâchant le bouton. 2 3.2 Premier pas : la fonction push Le premier pas consiste à détecter un clic de souris au sein du cercle. Écrire une fonction récursive val push : (int * int) -> unit tel que l’appel de fonction push (x,y) effectue les étapes suivantes : 1. Attendre un clic de souris dans la fenêtre 2. Vérifier que l’on a cliqué dans le cercle de centre (x,y) sinon revenir en 1. 3. Colorier le cercle en rouge. On utilise alors cette fonction de la manière suivante. 1. Dessiner un cercle noir de rayon 10 et placé en (100, 100). 2. Appeler la fonction push (100,100). 3. Attendre un clic de souris dans la fenêtre. 4. Quitter. 3.3 drag and drop Pour réaliser le déplacement du cercle, écrire tout d’abord une fonction val move : (int * int) -> (int * int) -> (int * int) -> (int * int) tel que l’appel move (x,y) (mx,my) (sx,sy) renvoie le couple (sx mx + x,sy - my + y). Ensuite, écrire une fonction de déplacement val drag : (int * int) -> (int * int) -> unit mutuellement récursive avec push tel que l’appel drag (x,y) (mx,my) effectue les étapes suivantes : 1. Attendre que la souris soit déplacée ou le bouton relâché. 2. Rappeler push si le bouton est relâché. 3. Sinon calculer les nouvelles coordonnées du cercle à l’aide de la fonction move. 4. Retourner en 1 Enfin, modifier la fonction push de manière à ce que l’étape 3 de son algorithme soit remplacée par un appel à la fonction drag. 3 3.4 Annexes Ici est présenté un extrait de la bibliothèque graphics. Pour l’utiliser : This library is implemented under the X11 windows system. Programs that use the graphics library must be linked as follows: ocamlc other options graphics.cma other files or start ocaml and type #load "graphics.cma";;. Voici les fonctions dont vous pourrez avoir besoin : – val open graph : string -> unit Show the graphics window or switch the screen to graphic mode. The graphics window is cleared and the current point is set to (0, 0). The string argument is used to pass optional information on the desired graphics mode, the graphics window size, and so on. Its interpretation is implementation-dependent. If the empty string is given, a sensible default is selected. Example : open graph " 300x300" – type status = { mouse_x : int ; X coordinate of the mouse mouse_y : int ; Y coordinate of the mouse button : bool ; true if a mouse button is pressed keypressed : bool ; true if a key has been pressed key : char ; the character for the key pressed } type event = | Button_down A mouse button is pressed | Button_up A mouse button is released | Key_pressed A key is pressed | Mouse_motion The mouse is moved | Poll Don’t wait; return immediately To specify events to wait for. – val wait next event : event list -> status Wait until one of the events specified in the given event list occurs, and return the status of 4 the mouse and keyboard at that time. If Poll is given in the event list, return immediately with the current status. If the mouse cursor is outside of the graphics window, the mouse x and mouse y fields of the event are outside the range 0..size x()-1, 0..size y()-1. Keypresses are queued, and dequeued one by one when the Key pressed event is specified. – val clear graph : unit -> unit Erase the graphics window. – val draw circle : int -> int -> int -> unit draw circle x y r draws a circle with center x,y and radius r. The current point is unchanged. Raise Invalid argument if r is negative. – val fill circle : int -> int -> int -> unit Fill a circle with the current color. The parameters are the same as for Graphics.draw circle[25.1]. – type color = int – val red : color – val set color : color -> unit 5 Set the current drawing color.