• Aucun résultat trouvé

Définition de macros (1)

N/A
N/A
Protected

Academic year: 2022

Partager "Définition de macros (1)"

Copied!
47
0
0

Texte intégral

(1)

c 2006 Marc Feeley IFT2030 page 220

Définition de macros (1)

Les macros en Lisp et Scheme tirent avantage de la similitude des données et expressions (la syntaxe des expressions est un sous-ensemble de la syntaxe des données)

Ainsi l’expression (and x y) se représente avec la liste (and x y)

Une macro sera vue comme une fonction de transformation qui prend en paramètre la

représentation des paramètres actuels de l’appel de macro, et qui retourne comme résultat la

représentation de l’expression qui est l’expansion de la macro

(2)

c 2006 Marc Feeley IFT2030 page 221

Définition de macros (2)

Exemple: définition d’une macro “and”

Il faut transformer (and X Y ) en (if X Y #f) (define-macro and

(lambda (x y)

(list ’if x y #f)))

Cette fonction de transformation est appelée à la

compilation sur l’ASA qui est justement représenté sous forme de liste

(3)

c 2006 Marc Feeley IFT2030 page 222

Définition de macros (3)

Ainsi le programme

(define-macro and (lambda (x y)

(list ’if x y #f))) (define f

(lambda (x)

(if (and (<= 0 x) (<= x 9)) (g x)

’erreur)))

sera expansé en

(define f

(lambda (x)

(if (if (<= 0 x) (<= x 9) #f) (g x)

’erreur)))

(4)

c 2006 Marc Feeley IFT2030 page 223

Définition de macros (4)

Puisque les formes spéciales prédéfinies et les macros utilisent la même syntaxe préfixe parenthésée, il n’y a pas de distinction d’utilisation entre elles et l’usager

peut ainsi intégrer naturellement ses propres extensions au langage de base

On parle de langage à domaine spécifique (“domain specific language”)

(5)

c 2006 Marc Feeley IFT2030 page 224

Définition de macros (5)

Par exemple, pour écrire des “boucles” dans le style de Pascal on aimerait une macro “for” avec la syntaxe

(for hvariablei := hexpr1i to hexpr2i do hexpr3i)

Cela permet de faire

(for i := 1 to 10 do (write i))

(6)

c 2006 Marc Feeley IFT2030 page 225

Définition de macros (6)

(for hvariablei := hexpr1i to hexpr2i do hexpr3i)

doit donc s’expandre à

(let ((debut hexpr1i) (fin hexpr2i)) (define boucle

(lambda (hvariablei)

(if (<= hvariablei fin) (begin hexpr3i

(boucle (+ hvariablei 1)))))) (boucle debut))

(7)

c 2006 Marc Feeley IFT2030 page 226

Définition de macros (7)

Définition basée sur “list”

(define-macro for

(lambda (variable _1 expr1 _2 expr2 _3 expr3) (list ’let

(list (list ’debut expr1) (list ’fin expr2)) (list ’define

’boucle

(list ’lambda

(list variable) (list ’if

(list ’<= variable ’fin) (list ’begin

expr3

(list ’boucle

(list ’+ variable 1))))))

’(boucle debut))))

(8)

c 2006 Marc Feeley IFT2030 page 227

Définition de macros (8)

L’utilisation de “list” pour cette macro donne une définition difficile à lire; il est mieux de construire des listes “quasi-constantes” à l’aide de la forme spéciale

quasiquote”:

`(a b ,X c (,Y d))

=

(list ’a ’b X ’c (list Y ’d))

La donnée construite correspond au patron avec des

valeurs calculées insérées aux endroits précédés d’une virgule

(9)

c 2006 Marc Feeley IFT2030 page 228

Définition de macros (9)

Définition basée sur “quasiquote”

(define-macro for

(lambda (variable _1 expr1 _2 expr2 _3 expr3)

`(let ((debut ,expr1) (fin ,expr2)) (define boucle

(lambda (,variable)

(if (<= ,variable fin)

(begin ,expr3 (boucle (+ ,variable 1)))))) (boucle debut))))

Ces définitions engendrent malheureusement un conflit de nom dans certains cas (par exemple, si la variable se nomme “fin” ou le corps fait référence à une

variable “fin”)

(10)

c 2006 Marc Feeley IFT2030 page 229

Définition de macros (10)

Solution 1: utilisation de fonctions d’O.S.

(define-macro for

(lambda (variable _1 expr1 _2 expr2 _3 expr3)

`((let ()

(define boucle

(lambda (i fin corps) (if (<= i fin)

(begin (corps i) (boucle (+ i 1) fin corps))))) boucle)

,expr1 ,expr2

(lambda (,variable) ,expr3))))

(11)

c 2006 Marc Feeley IFT2030 page 230

Définition de macros (11)

Solution 2: utilisation de “gensym” qui crée des

symboles qui sont garantis d’être différent de tout autre symbole

(define-macro for

(lambda (variable _1 expr1 _2 expr2 _3 expr3)

(let ((debut (gensym)) (fin (gensym)) (boucle (gensym)))

`(let ((,debut ,expr1) (,fin ,expr2)) (define ,boucle

(lambda (,variable)

(if (<= ,variable ,fin)

(begin ,expr3 (,boucle (+ ,variable 1)))))) (,boucle ,debut)))))

(12)

c 2006 Marc Feeley IFT2030 page 231

Définition de macros (12)

Solution 3: utilisation de “syntax-rules” (propre à R5RS) un mécanisme de définition de macros

“hygiéniques” définis par des règles de transformation à base de patrons

(define-syntax for

(syntax-rules (:= to do)

((for variable := expr1 to expr2 do expr3) (let ((debut expr1) (fin expr2))

(define boucle

(lambda (variable)

(if (<= variable fin) (begin expr3

(boucle (+ variable 1)))))) (boucle debut)))))

(13)

c 2006 Marc Feeley IFT2030 page 232

Interprètes et compilateurs (1)

Une machine est capable d’exécuter un programme exprimé dans son langage source Ls

Un interprète est un programme exprimé en langage hôte Lh capable d’exécuter un programme exprimé dans le langage source Ls

Un compilateur est un programme exprimé en langage hôte Lh capable de traduire un programme en langage source Ls en un programme en langage cible Lc

(14)

c 2006 Marc Feeley IFT2030 page 233

Interprètes et compilateurs (2)

La notation graphique suivante permet de spécifier les langages impliqués dans chaque cas:

Ls Lc

Lh Ls

Lh Ls

interprète

machine compilateur

Exemples

lang.

ass.

MIPS Scheme

MIPS L.M.

i386

L.M.

MIPS JVM

C MIPS

L.M.

C

MIPS

L.M.

MIPS MIPS

L.M. L.M. L.M.

(15)

c 2006 Marc Feeley IFT2030 page 234

Interprètes et compilateurs (3)

Un interprète ou compilateur exécutable peut être

obtenu en combinant des machine(s), interprète(s) et compilateur(s)

C

MIPS

L.M.

MIPS

L.M.

L.M.

MIPS

L.M.

MIPS JVM

C

L.M.

MIPS Scheme

MIPS L.M.

L.M.

MIPS

Scheme

C

MIPS L.M.

C

JVM

L.M.

MIPS Java JVM

C

Java C

Java

Java

JVM C

L.M.

MIPS C

L.M.

MIPS

JVM

L.M.

MIPS L.M.

MIPS

(16)

c 2006 Marc Feeley IFT2030 page 235

Interprètes et compilateurs (4)

Problème du “bootstrap” d’un compilateur: comment créer un nouveau compilateur pour un langage Ls?

Le compilateur peut être écrit dans n’importe quel langage hôte Lh

Évidemment c’est mieux si Lh est un langage de haut niveau (par exemple Scheme ou C) car si Lh est le

langage machine/assembleur cela prendra beaucoup d’efforts de développement (mais c’est ce qui a été fait pour FORTRAN!)

(17)

c 2006 Marc Feeley IFT2030 page 236

Interprètes et compilateurs (5)

S’il existe déjà un interprète ou compilateur pour Ls il est pratique d’écrire un compilateur autogène

c’est-à-dire où Ls = Lh

Gambit:

Scheme

L.M.

M68K

Scheme GAMBIT V1

Scheme

L.M.

M68K

Scheme GAMBIT V1

L.M.

Scheme

M68K MIT-SCH.

L.M.

M68K

L.M.

M68K Scheme

L.M.

M68K GAMBIT V1

L.M.

M68K

L.M.

M68K Scheme

L.M.

M68K

L.M.

M68K GAMBIT V2 Scheme

L.M.

M68K

Scheme GAMBIT V2

L.M.

M68K Scheme

L.M.

M68K

Scheme GAMBIT V2

Scheme

L.M.

M68K

L.M.

M68K GAMBIT V2

(18)

c 2006 Marc Feeley IFT2030 page 237

Interprètes et compilateurs (6)

Avantages

1. autosuffisance (pas besoin d’un autre compilateur ou interprète pour la maintenance et extensions)

2. amélioration de la qualité du code généré a un impact sur la performance du compilateur (p.e. réduction du temps de compilation)

(19)

c 2006 Marc Feeley IFT2030 page 238

Interprètes et compilateurs (7)

Le cas analogue pour les interprètes, c’est-à-dire Ls = Lh, se nomme interprète méta-circulaire

La compilation d’un interprète méta-circulaire permet d’obtenir un interprète exécutable

Exemple de l’interprète Gambit:

L.M.

M68K

L.M.

Scheme

M68K GSI Scheme

GSI

Scheme Scheme

L.M.

M68K

L.M.

M68K GSC

(20)

c 2006 Marc Feeley IFT2030 page 239

Interprètes et compilateurs (8)

De plus, un interprète méta-circulaire peut servir à décrire et éclaircir la sémantique d’un langage de programmation et le fonctionnement des interprètes (méta-circulaires ou non)

(21)

c 2006 Marc Feeley IFT2030 page 240

Interprète méta-circulaire (1)

L’implantation d’un interprète méta-circulaire pour Scheme est simplifiée par le fait que la syntaxe du

langage source est un sous-ensemble de la syntaxe des données

Ainsi la liste (set! x (cdr x)) peut servir de représentation pour

l’expression (set! x (cdr x))

De plus, il est possible de représenter les données manipulées par le programme interprété par

elles-mêmes (par exemple si le programme interprété exécute (cons 1 2) l’interprète construira la paire (1 . 2) directement)

(22)

c 2006 Marc Feeley IFT2030 page 241

Interprète méta-circulaire (2)

Nous allons écrire un interprète pour un

sous-ensemble de Scheme (petit nombre de fonctions et seulement les formes spéciales quote, set!,

lambda, begin, cond, define et define-macro)

Problèmes principaux

1. représentation de l’environnement d’évaluation 2. représentation des fonctions

(23)

c 2006 Marc Feeley IFT2030 page 242

Interprète méta-circulaire (3)

Commençons par un interprète simple qui traite seulement les constantes et l’appel de fonction

L’interprète prend la représentation d’une expression en paramètre et calcule sa valeur

(eval ’(+ (* 2 3) 4)) => 10

Implantation de l’interprète:

(define eval (lambda (e)

(cond ((pair? e)

(let ((op (car e))

(a1 (eval (cadr e))) (a2 (eval (caddr e))))

(cond ((eq? op ’+) (+ a1 a2)) ((eq? op ’-) (- a1 a2)) ((eq? op ’*) (* a1 a2))

(else (error "erreur"))))) (else

e))))

(24)

c 2006 Marc Feeley IFT2030 page 243

Interprète méta-circulaire (4)

Voici une version plus extensible:

(define eval (lambda (e)

(cond ((pair? e)

(let ((fn (lookup (car e) table)) (a1 (eval (cadr e)))

(a2 (eval (caddr e)))) (fn a1 a2)))

(else e)))) (define lookup

(lambda (sym env)

(let ((x (assoc sym env)))

(if x (cdr x) (error "erreur"))))) (define table

(list (cons ’+ +) (cons ’- -) (cons ’* *) (cons ’/ /)

(cons ’expt expt)))

(25)

c 2006 Marc Feeley IFT2030 page 244

Interprète méta-circulaire (5)

Et encore plus extensible:

(define eval (lambda (e)

(cond ((pair? e)

(let ((fn (lookup (car e) table))) (apply fn (map eval (cdr e))))) (else

e))))

; note: (apply f ’(1 2 3)) = (f 1 2 3) (define table

(list (cons ’+ +) (cons ’- -) (cons ’* *) (cons ’/ /)

(cons ’expt expt) (cons ’log log) (cons ’cos cos)))

(eval ’(+ (log 1) (cos 0) 5)) => 6

(26)

c 2006 Marc Feeley IFT2030 page 245

Interprète méta-circulaire (6)

Pour traiter les variables on ajoute un paramètre environnement à eval:

(define eval

(lambda (e env)

(cond ((symbol? e)

(lookup e env)) ((pair? e)

(let ((ev (lambda (x) (eval x env)))) (apply (ev (car e))

(map ev (cdr e))))) (else

e)))) (define table

(list (cons ’x 5) (cons ’+ +) (cons ’- -) (cons ’* *) (cons ’/ /)))

(eval ’(+ 1 x x) table) => 11

(27)

c 2006 Marc Feeley IFT2030 page 246

Interprète méta-circulaire (7)

L’environnement d’évaluation est donc représenté par une liste d’association (qui associe la valeur d’une variable avec le symbole qui est le nom de la variable)

Par exemple si l’environnement contient uniquement les variables x, y et z et que ces variables ont

respectivement les valeurs 1, 2 et 3:

((x . 1) (y . 2) (z . 3))

qui a la forme suivante en mémoire:

()

z 3

y 2

x 1

(28)

c 2006 Marc Feeley IFT2030 page 247

Interprète méta-circulaire (8)

L’accès aux variables se fait avec assoc:

(define env-read

(lambda (env var)

(cdr (assoc var env))))

(define env-set! ; supporte ´egalement "define"

(lambda (env var val)

(cond ((eq? (car (car env)) var) (set-cdr! (car env) val)) ((null? (cdr env))

(set-cdr! env (list (cons var val)))) (#t

(env-set! (cdr env) var val)))))

(29)

c 2006 Marc Feeley IFT2030 page 248

Interprète méta-circulaire (9)

Le traitement correct des formes spéciales lambda et define demande d’ajouter des nouvelles variables à l’environnement

Pour lambda on peut simplement ajouter des nouvelles associations à l’avant de l’environnement; ainsi

l’environnement construit pendant l’évaluation de

((lambda (a y) (list a y z)) 123 999) est

y 2

y

a 123 999 x 1

()

z 3

(30)

c 2006 Marc Feeley IFT2030 page 249

Interprète méta-circulaire (10)

Extension de l’environnement

(define env-extend

(lambda (env parms vals) (cond ((null? parms)

env) (#t

(cons (cons (car parms) (car vals)) (env-extend env

(cdr parms)

(cdr vals)))))))

Note: l’ancienne association pour y est cachée (aux yeux de env-read et env-set!) ce qui implante correctement la portée lexicale

(31)

c 2006 Marc Feeley IFT2030 page 250

Interprète méta-circulaire (11)

Pour define, si la variable existe déjà on change sa valeur comme pour un set!

Sinon on doit ajouter une nouvelle association à l’arrière de l’environnement destructivement

Ainsi l’environnement sera modifié comme suit pendant l’évaluation de (define b 555)

y 2

x 1

() ()

z 3 b 555

(32)

c 2006 Marc Feeley IFT2030 page 251

Interprète méta-circulaire (12)

L’environnement doit être étendu destructivement pour implanter correctement les références “vers l’avant”:

(define f (lambda (a) (list a b))) (define b 555)

Le même mécanisme est utilisé pour implanter define-macro

(33)

c 2006 Marc Feeley IFT2030 page 252

Interprète méta-circulaire (13)

Il y a 2 types de fonctions: les primitives (les fonctions prédéfinies) et les fermetures (créées par l’évaluation de lambda-expressions)

Pour simplifier, les fonctions sont représentées par des paires

• si le car est le symbole prim, la paire représente la fonction primitive dont le nom est le champ cdr,

p.ex. (prim . write)

• sinon, la paire représente une fermeture, le champ car donne les paramètres et le corps de la

lambda-expression qui a engendré cette fermeture et le champ cdr est l’environnement dans lequel cette lambda-expression fut évaluée

(34)

c 2006 Marc Feeley IFT2030 page 253

Interprète méta-circulaire (14)

Par exemple, si

(lambda (a y) (list a y z)) est évaluée dans l’environnement

((x . 1) (y . 2) (z . 3)) le résultat est

(((a y) (list a y z)) . ((x . 1)(y . 2)(z . 3)))

Cette fermeture sera scrutée par l’interprète lors de son appel

(35)

c 2006 Marc Feeley IFT2030 page 254

Interprète méta-circulaire (15)

La fonction principale de l’interprète est la fonction eval:

(eval hrepr d’une expressioni henvironnementi)

=> hvaleur de l’expressioni Par exemple:

(eval ’(cons 1 2) global-env) => (1 . 2)

La boucle d’interaction “read-eval-print” de l’interprète s’implante simplement avec:

(define repl (lambda ()

(begin

(write ’>)

(write (eval (read) global-env)) (newline)

(repl))))

(36)

c 2006 Marc Feeley IFT2030 page 255

Interprète méta-circulaire (16)

1. (define global-env

2. (list ’(read . (prim . read )) ’(newline . (prim . newline))

3. ’(write . (prim . write )) ’(symbol? . (prim . symbol?))

4. ’(null? . (prim . null? )) ’(pair? . (prim . pair? ))

5. ’(car . (prim . car )) ’(cdr . (prim . cdr ))

6. ’(cadr . (prim . cadr )) ’(cons . (prim . cons ))

7. ’(set-cdr! . (prim . set-cdr!)) ’(assoc . (prim . assoc ))

8. ’(eq? . (prim . eq? )) ’(list . (prim . list ))))

9.

10. (define env-read

11. (lambda (env var)

12. (cdr (assoc var env))))

13.

14. (define env-set!

15. (lambda (env var val)

16. (cond ((eq? (car (car env)) var) (set-cdr! (car env) val))

17. ((null? (cdr env)) (set-cdr! env (list (cons var val))))

18. (#t (env-set! (cdr env) var val)))))

19.

20. (define env-extend

21. (lambda (env parms vals)

22. (cond ((null? parms) env)

23. (#t (cons (cons (car parms) (car vals))

24. (env-extend env (cdr parms) (cdr vals)))))))

(37)

c 2006 Marc Feeley IFT2030 page 256

Interprète méta-circulaire (17)

25. (define eval

26. (lambda (expr env)

27. (cond ((symbol? expr) (env-read env expr))

28. ((pair? expr) (eval-composite (car expr) (cdr expr) env))

29. (#t expr))))

30.

31. (define eval-composite

32. (lambda (x lst env)

33. (cond ((assoc x macros) (eval (apply (env-read macros x) lst) env))

34. ((eq? x ’defmacro) (env-set! macros (car lst) (eval (cadr lst) env)))

35. ((eq? x ’set!) (env-set! env (car lst) (eval (cadr lst) env)))

36. ((eq? x ’quote) (car lst))

37. ((eq? x ’lambda) (eval-lambda lst env))

38. ((eq? x ’begin) (eval-begin #f lst env))

39. ((eq? x ’cond) (eval-cond lst env))

40. (#t (eval-call x lst env)))))

41.

42. (define eval-lambda

43. (lambda (parms-and-body def-env)

44. (cons parms-and-body def-env)))

45.

46. (define eval-begin

47. (lambda (val lst env)

48. (cond ((null? lst) val)

49. (#t (eval-begin (eval (car lst) env) (cdr lst) env)))))

50.

51. (define eval-cond

52. (lambda (lst env)

53. (cond ((eval (car (car lst)) env) (eval (cadr (car lst)) env))

54. ((pair? (cdr lst)) (eval-cond (cdr lst) env)))))

55.

56. (define eval-call

57. (lambda (fn-expr arg-exprs env)

58. (apply (eval fn-expr env) (eval-list arg-exprs env))))

59.

60. (define eval-list

61. (lambda (lst env)

62. (cond ((null? lst) ’())

63. (#t (cons (eval (car lst) env)

64. (eval-list (cdr lst) env))))))

(38)

c 2006 Marc Feeley IFT2030 page 257

Interprète méta-circulaire (18)

65. (define apply

66. (lambda (fn lst)

67. (cond ((eq? (car fn) ’prim)

68. (cond ((eq? (cdr fn) ’read) (read))

69. ((eq? (cdr fn) ’newline) (newline))

70. ((eq? (cdr fn) ’write) (write (car lst)))

71. ((eq? (cdr fn) ’symbol?) (symbol? (car lst)))

72. ((eq? (cdr fn) ’null?) (null? (car lst)))

73. ((eq? (cdr fn) ’pair?) (pair? (car lst)))

74. ((eq? (cdr fn) ’car) (car (car lst)))

75. ((eq? (cdr fn) ’cdr) (cdr (car lst)))

76. ((eq? (cdr fn) ’cadr) (cadr (car lst)))

77. ((eq? (cdr fn) ’cons) (cons (car lst) (cadr lst)))

78. ((eq? (cdr fn) ’set-cdr!) (set-cdr! (car lst) (cadr lst)))

79. ((eq? (cdr fn) ’assoc) (assoc (car lst) (cadr lst)))

80. ((eq? (cdr fn) ’eq?) (eq? (car lst) (cadr lst)))

81. ((eq? (cdr fn) ’list) lst)))

82. (#t

83. (eval (cadr (car fn))

84. (env-extend (cdr fn) (car (car fn)) lst))))))

85.

86. (define macros

87. (list (cons ’define

88. (eval-lambda ’((var expr) (list ’set! var expr)) global-env))))

89.

90. (define repl

91. (lambda ()

92. (begin (write ’>)

93. (write (eval (read) global-env))

94. (newline)

95. (repl))))

(39)

c 2006 Marc Feeley IFT2030 page 258

Interprète méta-circulaire (19)

Exemple 1: trace de l’évaluation de list

| > (eval ’list ’((read prim . read) ...))

| > (env-read ’((read prim . read) ...) ’list)

| (prim . list)

Exemple 2: trace de l’évaluation de

(set! read (list 1 2))

| > (eval ’(set! read (list 1 2)) ’((read prim . read) ...))

| > (eval-composite ’set! ’(read (list 1 2)) ’((read ...)))

| | > (eval ’(list 1 2) ’((read prim . read) ...))

| | > (eval-composite ’list ’(1 2) ’((read prim . read) ...))

| | > (eval-call ’list ’(1 2) ’((read prim . read) ...))

| | | > (eval ’list ’((read prim . read) ...))

| | | > (env-read ’((read prim . read) ...) ’list)

| | | (prim . list)

| | | > (eval-list ’(1 2) ’((read prim . read) ...))

| | | | > (eval 1 ’((read prim . read) ...))

| | | | 1

| | | | > (eval-list ’(2) ’((read prim . read) ...))

| | | | | > (eval 2 ’((read prim . read) ...))

| | | | | 2

| | | | | > (eval-list ’() ’((read prim . read) ...))

| | | | | ()

| | | | (2)

| | | (1 2)

| | > (apply ’(prim . list) ’(1 2))

| | (1 2)

| > (env-set! ’((read prim . read) ...) ’read ’(1 2))

| #<void>

(40)

c 2006 Marc Feeley IFT2030 page 259

Interprète méta-circulaire (20)

Exemple 3: ((lambda (write) (write read)) car)

| > (eval ’((lambda (write) (write read)) car) ’((read 1 2) ...))

| > (eval-composite ’(lambda (write) (write read)) ’(car) ’(...))

| > (eval-call ’(lambda (write) (write read)) ’(car) ’((read 1 2) ...))

| | > (eval ’(lambda (write) (write read)) ’((read 1 2) ...))

| | > (eval-composite ’lambda ’((write) (write read)) ’((read 1 2) ...))

| | > (eval-lambda ’((write) (write read)) ’((read 1 2) ...))

| | (((write) (write read)) . ((read 1 2) ...))

| | > (eval-list ’(car) ’((read 1 2) ...))

| | | > (eval ’car ’((read 1 2) ...))

| | | > (env-read ’((read 1 2) ...) ’car)

| | | (prim . car)

| | | > (eval-list ’() ’((read 1 2) ...))

| | | ()

| | ((prim . car))

| > (apply ’(((write) (write read)) . ((read 1 2) ...)) ’((prim . car)))

| | > (env-extend ’((read 1 2) ...) ’(write) ’((prim . car)))

| | | > (env-extend ’((read 1 2) ...) ’() ’())

| | | ((read 1 2) ...)

| | ((write prim . car) (read 1 2) ...)

| > (eval ’(write read) ’((write prim . car) (read 1 2) ...))

| > (eval-composite ’write ’(read) ’((write prim . car) (read 1 2) ...))

| > (eval-call ’write ’(read) ’((write prim . car) (read 1 2) ...))

| | > (eval ’write ’((write prim . car) (read 1 2) ...))

| | > (env-read ’((write prim . car) (read 1 2) ...) ’write)

| | (prim . car)

| | > (eval-list ’(read) ’((write prim . car) (read 1 2) ...))

| | | > (eval ’read ’((write prim . car) (read 1 2) ...))

| | | > (env-read ’((write prim . car) (read 1 2) ...) ’read)

| | | (1 2)

| | | > (eval-list ’() ’((write prim . car) (read 1 2) ...))

| | | ()

| | ((1 2))

| > (apply ’(prim . car) ’((1 2)))

| 1

(41)

c 2006 Marc Feeley IFT2030 page 260

Programmation logique

Prolog est le langage principal qui offre ce style

Inventé en 1972 par Alain Colmerauer

Applications principales:

• Traitement de la langue naturelle

• Traitement symbolique et I.A.

Particularités:

• Unification et filtrage (“pattern matching”)

• Retour arrière (“backtracking”)

• Interactif

• Déclaratif (un programme exprime des relations entre objets)

(42)

c 2006 Marc Feeley IFT2030 page 261

Relations (1)

Déf: une relation binaire sur les ensembles X1 et X2 est un ensemble de couples de la forme hx1,x2i, où x1 est élément de X1 et x2 est élément de X2

Exemple

2

5 4 3 1

2

5 4 3 1

X1 X2

soit X1 = {1..5} et X2 = {1..5}

relation R sur X1 et X2: "x1 est un facteur de x2"

<2,2>, <2,4>, <3,3>, <4,4>, <5,5> } R = { <1,1>, <1,2>, <1,3>, <1,4>, <1,5>,

1 1 1 1 1 2 2 3 4 5

1 2 3 4 5 2 4 3 4 5

X2 X1

(43)

c 2006 Marc Feeley IFT2030 page 262

Relations (2)

Déf: une relation N-aire sur les ensembles X1...Xn est un ensemble de tuples de la forme hx1,x2,...,xni, où xi est élément de Xi

Exemple: relation sur les 3 ensembles “Nom”, “Code” et

“Note”

Nom Code Note

"Luc Dubuc" "DUBL123456" 76

"Julie Roy" "ROYJ123456" 57

"Jean Coutu" "COUJ123456" 89

(44)

c 2006 Marc Feeley IFT2030 page 263

Relations (3)

Déf: une fonction de X1 (domaine) vers X2 (l’image) est une relation binaire qui met en relation au plus un élément de X2 avec chaque élément de X1

Exemple

relation: relation:

age de x1 est x2 x1 plus vieux que x2

X1 X2 X1 X2

"Luc Dubuc" 45 "Jean Coutu" "Luc Dubuc"

"Julie Roy" 18 "Jean Coutu" "Julie Roy"

"Jean Coutu" 60 "Luc Dubuc" "Julie Roy"

est une fonction n’est pas une fonction

(45)

c 2006 Marc Feeley IFT2030 page 264

Relations (4)

Les langages fonctionnels permettent de manipuler aisément les relations binaires qui sont des fonctions

Les langages logiques permettent de manipuler n’importe quelles relations

Avantage: permet de faire des calculs “dans les 2 sens”

(passer de X1 à X2, ou l’inverse)

Exemple 1

relation: le genre de x1 est x2

X1 X2

"Luc Dubuc" homme

"Julie Roy" femme

"Jean Coutu" homme

(46)

c 2006 Marc Feeley IFT2030 page 265

Relations (5)

En programmation fonctionnelle il serait naturel

d’implanter une fonction “genre” qui retourne le genre étant donné le nom

Cela permettrait de répondre facilement à la question:

quel est le genre de “Julie Roy”?

Cependant cette fonction ne permet pas de répondre à la question: quels sont tous les hommes?

En programmation logique il sera tout aussi facile de spécifier x2 pour obtenir le ou les x1 qui sont en

relation, que l’inverse

(47)

c 2006 Marc Feeley IFT2030 page 266

Relations (6)

Exemple 2: concaténation de chaînes

relation: la concat´enation de x1 et x2 donne x3

X1 X2 X3

"" "" ""

"" "a" "a"

"a" "" "a"

"" "ab" "ab"

"a" "b" "ab"

"ab" "" "ab"

"" "abc" "abc"

"a" "bc" "abc"

"ab" "c" "abc"

"abc" "" "abc"

... et ainsi de suite pour toutes les chaines

Quelle est la concaténation de "a" et "b"?

Qu’est-ce qui, concaténé à "a" donne "ab"?

Quelles sont les 2 chaînes x et y qui lorsqu’on les concatènes donnent "ab"?

Références

Documents relatifs

L'aire de la croix est égale à l'aire totale du carré privé de 4 fois l'aire du carré de côté x.. Donc l'aire de la croix vaut 4² −

Déterminer la température du corps, arrondie au degré près, au bout de 20 minutes, puis au bout de 30 minutes.. Déterminer graphiquement une valeur approchée du temps au bout duquel

La commande :Input “A=”,A affiche A= à l’écran, attend une réponse et stocke cette valeur dans A La commande :Prompt A n’affiche rien à l’écran, attend une réponse et

Question sur 2 pts : Un compilateur est un programme qui traduit un pro- gramme source écrit dans un langage de haut niveau (i.e. C) en un programme cible sémantiquement

Le laboratoire estime qu’un test est fiable si sa valeur prédictive, c'est-à-dire la probabilité qu’un animal soit malade sachant que le test est positif, est supérieure à

Coloriez soigneusement les cases et les lignes afin d’aider Ozobot à se rendre de toute urgence à l’hôpital.. Il doit s'allumer en bleu pour montrer qu'il est

• Déclare une variable x de type int – entier- de valeur initiale 4, utilisable ensuite dans une instruction. 65 MAP

Type 2 : Erreurs d’exécution : Après que la compilation soit faite sans erreur, il peut se trouver que le travail fait par le programme soit erroné, par exemple : division par