Légende urbaine.
De façon générale, une fonction ou procédure se définie par
- en entrée, l’environnement (variables globales, état de la mémoire, de la machine, etc) et les arguments.
- en sortie, les effets de bords (modifications des variables, globales, de l’environnement en général (mémoire écran, disques, etc) et du résultat.
Un langage fonctionnel met l’accent sur les arguments et le résultat. Par ailleurs, il n’y a pas de différence entre une fonction et un objet.
Exemple: tu peux définir la composition en Caml par
[code]let composition f g = function x -> f (g x);;
let prefix *$ = composition;;
[/code]
Tu obtiens
et par exemple
let f x = 2*x+1;;
let g = f *$ f;;
f (f 3);;
g 3;;
qui te donne
[quote]
f : int -> int =
g : int -> int =
#f (f 3);;
- : int = 15
#g 3;;
- : int = 15
#[/quote]
C’est extrèmement puissant. Les boucles se font de plusieurs manières:
Un code en impératif comme
[code]let addition n =
let s = ref 0 in
begin
for i = 1 to n do
s:=!s+i;
done;
!s
end;;
addition : int -> int =
#addition 15;;
- : int = 120
[/code]
se fait comme
[code]#let addition =
let rec boucle r = function
| 0 -> r
| i -> (boucle (r+i) (i-1))
in boucle;;
addition : int -> int -> int =
#addition 15;;
L’apothéose est que tu peux montrer par exemple que la récursion ne rajoute te rien dès que tu peux manipuler des fonctions. Dans ce qui suit, on formalise se qu’est une fonction récursive i.e définie par
f(x) = si (t(x)) alors g(x) sinon ex(x,f(h(x)))
pour factorielle, tu as
t(x) = (x==0)
g(x) = 1 (uniquement appelé pour x=0 en fait)
h(x) = x-1
ex(x,y) = xy (on a n! = n((n-1)!)
La fonction (calcule t g h ex) renvoit la fonction factorielle si on lui fournit les bonnes fonctions.
[code]#(calcule t_fact g_fact h_fact ex_fact) 7;;
Ceci n’est faisable qu’en fonctionnel. Il y a deux écriture de la fonction calcule: la première est récursive et se fait très simplement (utilisation de rec). La deuxième est impérative avec des références et des boucles et non récursive. Son écriture est une méthode de dérécursification de n’importe quelle fonction récursive et est également la preuve qu’un langage récursif (avec des fonctions réentrantes) n’est pas plus puissant qu’un langage impératif non récursif.
[code] Caml Light version 0.76
#let calcule t g h ex x =
let rec fonction xp =
if (t xp) then (g xp)
else (ex xp (fonction (h xp)))
in (fonction x);;
calcule :
('a -> bool) -> ('a -> 'b) -> ('a -> 'a) -> ('a -> 'b -> 'b) -> 'a -> 'b =
#let t_fact = eq_int 0;;
t_fact : int -> bool =
#let g_fact _ = 1;;
g_fact : 'a -> int =
#let h_fact x = x-1;;
h_fact : int -> int =
#let ex_fact x y = x*y;;
ex_fact : int -> int -> int =
#let fact = (calcule t_fact g_fact h_fact ex_fact);;
fact : int -> int =
#(fact 7);;
- : int = 5040
#let recursif_terminal t g h x = let xp = ref x in
begin
while not (t !xp) do xp:=(h !xp);done;
(g !xp)
end;;
recursif_terminal : ('a -> bool) -> ('a -> 'b) -> ('a -> 'a) -> 'a -> 'b =
#let compose f g = function x -> (f (g x));;
compose : ('a -> 'b) -> ('c -> 'a) -> 'c -> 'b =
#let prefix *$ = compose;;
*$ : ('a -> 'b) -> ('c -> 'a) -> 'c -> 'b =
#let calcule t g h ex x =
let g_term (f,xp) = (f (g xp))
and t_term (_,xp) = (t xp)
and h_term (f,xp) =
let f_rajoute = (function y -> (ex xp y))
in ((f_rajoute *$ f),(h xp))
in recursif_terminal t_term g_term h_term ((function y-> y),x);;
calcule :
('a -> bool) -> ('a -> 'b) -> ('a -> 'a) -> ('a -> 'b -> 'b) -> 'a -> 'b =
#let fact = (calcule t_fact g_fact h_fact ex_fact);;
fact : int -> int =
#(fact 7);;
- : int = 5040
#[/code]
Le tout est très court. Fais ça en C et on en reparlera 