IFT359 – Programmation fonctionnelle Thème 02 B partie A introduction au langage fonctionnel choisi 1
LES FORMES SYNTAXIQUES LEURS ÉVALUATIONS DÉTERMINENT LE COMPORTEMENT DU PROGRAMME Thème 02 B 2
Formes syntaxiques set! (set! id expr) –id doit être une variable liée par une variable ayant déjà une valeur i.e. id doit être accessible dans l’environnement où est évalué l’expression –expr est évalué et remplace l’ancienne valeur –un set! expression retourne #. –Évaluation par environnement d’un set! expression 1.trouver id dans la chaîne d’environnement 2.évaluer expr dans l’environnement courant 3.remplacer l’ancienne valeur de id par celle qui vient d’être trouvée set! ne doit pas être utilisé sauf si on l’autorise expressément –l’affectation est contraire à l’esprit de la programmation fonctionnelle 3
Formes syntaxiques quote (quote datum) –datum est n’importe quel entité retourné par le reader (une entité pas deux ou plus) –(quote datum) retourne datum ' datum est une abbréviation syntaxique de (quote datum) Retour sur le type symbole –(quote identificateur) retourne un symbole dont la valeur est identificateur un symbole est un objet de type primitif en scheme il peut référencé par un autre identificateur (define aaa ‘xxx) aaa xxx 4
Formes syntaxiques if (if test-expr then-expr else-expr) –connu –si l’évaluation de test-expr est vraie (n’est pas #f) alors then-expr est évalué sinon else-expr est évalué –test-expr then-expr else-expr sont évalués si nécessaire dans l’environnement courant tous les types d’expression sont évalués dans l’environnement courant l’environnement courant d’une expression est toujours celui du bloc lexical contenant l’expression une application voit tous ses éléments évalués dans l’environnement courant mais le corps de la fonction est évalué dans un nouvel environnement dont le parent est celui où la fonction a été défini. –test-expr then-expr else-expr doivent être des expr selon la syntaxe de drRacket en pratique cela n’élimine que define, define-syntax, define-values, require voir la section du fichier pour la syntaxe complète d’un programme après « expansion »fichier –mais c’est assez ardu 5
Formes syntaxiques begin begin deux versions –(begin expr1 exprs...) est une expression –peut être utilisé tout partout où une expression peut être utilisé retourne l’évaluation de la dernière expression –(begin form...) est interprété sous cette version que dans les endroits où les définitions sont autorisées son contenu est simplement inséré à l’intérieur du programme, –c’est exactement comme s’il n’y avait pas de begin form est pour ainsi dire n’importe élément syntaxique reconnu –(define id expr) est une forme mais non un expression Les séquences ne font pas partie des langages fonctionnels mais leur utilisation facilite de beaucoup les interactions avec les différentes parties du systèmes d’exploitation –Toutes les expressions expr1 exprs … sauf la dernière ne sont présent que pour leurs effets de bord 6
Formes syntaxiques cond cond (cond cond-clause...) –cond-clause [test-expr then-body...+] | [else then-body...+] | [test-expr => proc-expr] | [test-expr] –la clause else doit être la dernière –la clause [test-expr => proc-expr] si test-expr ≠ #f alors la clause retourne (proc-expr test-expr) –Si aucun cond-clause est applicable cond retourne # 7
Formes syntaxiques Exemple de cond expressioncond 8 (cond [1 2]) 2 (cond [else 'elsesymbol]) 'elsesymbol (cond [(= 2 3) 'bonjour] [else 'elsesymbol]) 'elsesymbol (cond [(= 2 3) 'bonjour] [3 => (λ(x) (+ x 2))] [else 'elsesymbol]) 5 (cond [(= 2 3) 'bonjour] [#f => (λ(x) (+ x 2))] ['terminé]) 'terminé
Formes syntaxiques case case (case val-expr case-clause...) –case-clause [(datum...) then-body...+] –datum signifie que les données doivent être déjà évaluées [else then-body...+] –le else-clause, s’il existe, doit être le dernier –si aucun case-clause est applicable retourne # 9 (case (- 7 2) [(1 2 3) 'small] [( ) 'big] [else 'ok]) 'ok (case (+ 7 5) [(1 2 3) 'small] [( ) 'big]) 'big (case (- 7 5) [(1 2 3) 'small] [( ) 'big]) 'small
Formes syntaxiques and (and expr...) –évalue les expressions une à la fois à partir de gauche –retourne #f aussitôt qu’une des expressions retourne faux. –sinon retourne la valeur de la dernière expression –(and) retourne #t (and) #t (and 1 2 3) 3 (and 1 2 #f 4) #f 10
Formes syntaxiques or (or expr...) –retourne la valeur de la première expression qui n’est pas #f –sinon #f incllant s’il n’y a pas d’expression (or) #f (or 1 2 3) 1 (or #f 2 #f 4) 2 11
Formes syntaxiques when et unless (when test-expr body...+) –si l’évaluation de text-expr n’est pas #f alors body …+ est exécuté et la l’évaluation de la dernière expression est retourné (when ) 3 (when #f 1 2 3) # (unless test-expr body...+) –équivalent à (when (not test-expr) body...+) (unless #f 1 2 3) 3 (unless ) # 12
Formes syntaxiques let (let ([id val-expr]...) body...+) est équivalant à –((λ (id...) body...+) val-expr...) (let ([x 2][y 3]) (+ x y)) est équivalant à ((λ (x y) (+ x y)) 2 3) pour faire l’évaluation par environnement, il faut transformer un let expression en une application de fonction équivalente 13
Formes syntaxiques named let (let proc-id ([id init-expr]...) body...+) est équivalant à (let ([proc-id (void)] [id init-expr]...) (set! proc-id (λ (id...) body...+)) (proc-id id...)) 14 (let fac ([n 10]) (if (zero? n) 1 (* n (fac (sub1 n))))) (let ([fac (void)] [n 10]) (set! fac (λ (n) (if (zero? n) 1 (* n (fac (sub1 n)))))) (fac n))
Évaluation par environnement (define x 5) (define f (λ (x) (* x x))) (let ([x 3] [y (+ x 10)]) (+ x y)) (define x 5) (define f (λ (x) (* x x))) ((λ (x y) (+ x y)) 3 (+ x 10)) 15
Situation initiale 16
Évaluation du premier élément de l’application 17
Évaluation des éléments 2 et 3 de l’application 18 3 et (+ x 10) sont évalués dans l’env courant (en vert) 3 retourne 3 (+ x 10) (+ 5 10) 15 car x vaut 5 dans l’env. courant et que le + (comme toutes les procédures primitives) sont évalués magiquement en prenant leurs argument dans l’environnement courant.
Évaluation de l’application Création de l’environnement 19
Évaluation du corps de la fonction Dans l’environnement courant (coloré en vert) on évalue le corps de la fonction. 1.(* x y) est évalué 2.(+ x y) est évalué et, comme c’est le dernier, son résultat est retourné 20
Formes syntaxiques let* (let* ([id val-expr]...) body...+) est équivalant à (let ([id0 val-expr0]) (let ([id1 val-expr1])... body...+)...) 21 (let* ([x 5] [y (+ x 2)]) (* x y)) (let ([x 5]) (let ([y (+ x 2)]) (* x y)))
Formes syntaxiques letrec (letrec ([id val-expr]...) body...+) est équivalant à (let ([id (void)]...) (set! id val-expr)... body...+) 22 (letrec ([is-even? (λ (n) (or (zero? n) (is-odd? (sub1 n))))] [is-odd? (λ (n) (and (not (zero? n)) (is-even? (sub1 n))))]) (is-odd? 11)) prochaine diapositive
Formes syntaxiques letrec 23 (letrec ([is-even? (λ (n) (or (zero? n) (is-odd? (sub1 n))))] [is-odd? (λ (n) (and (not (zero? n)) (is-even? (sub1 n))))]) (is-odd? 11)) (let ([is-even? (void)][is-odd? (void)]) (set! is-even? (λ (n) (or (zero? n) (is-odd? (sub1 n))))) (set! is-odd? (λ (n) (and (not (zero? n)) (is-even? (sub1 n))))) (is-odd? 11))
Retour sur l’évaluation des define 24 L’évaluation des define au top-level sont évalués comme nous l’avons décrits précédemment. Cependant l’évaluation des define qui sont dans un sous-espace lexical sont traités comme s’ils faisaient partie d’un letrec. (let () (define f (λ (x) (if (= x 0) 'terminéf (g (- x 1))))) (+ 3 4) (define g (λ (x) (if (= x 0) 'terminég (f (- x 1))))) (+ 8 9) (f 3)) (letrec-values ([(f) (λ (x) (if (= x 0) 'terminéf (g (- x 1))))] [() (begin (+ 3 4) (values))] [(g) (λ (x) (if (= x 0) 'terminég (f (- x 1))))]) (+ 8 9) (f 3))
Retour sur l’évaluation des define 25 Si on utilise le macro stepper, on voit que DrRacket fait parfois plusieurs optimisations. Par exemple - ce n’est pas toujours un letrec-values mais parfois un let-values - et ces derniers peuvent être imbriqués comme pour faire un let*- values (let () (define f (λ (x) (if (= x 0) 'terminéf (g (- x 1))))) (+ 3 4) (define g (λ (x) (if (= x 0) 'terminég (f (- x 1))))) (+ 8 9) (f 3)) (letrec-values ([(f) (λ (x) (if (= x 0) 'terminéf (g (- x 1))))] [() (begin (+ 3 4) (values))] [(g) (λ (x) (if (= x 0) 'terminég (f (- x 1))))]) (+ 8 9) (f 3))