Fonctions du 1er ordre - LRDE

Transcription

Fonctions du 1er ordre - LRDE
Programmation
Fonctionnelle
Didier Verna
E PITA
Généralités
Lambda
En argument
Généralités
Motifs
Approches Fonctionnelles de la
Programmation
Fonctions du 1er ordre
En retour
Généralités
Motifs
Comme objets
Didier Verna
[email protected]
http://www.lrde.epita.fr/˜didier
1/38
Table des matières
Programmation
Fonctionnelle
Didier Verna
E PITA
Généralités
1
Généralités
2
Fonctions anonymes
3
Arguments fonctionnels
Généralités
Motifs courants
4
Retours fonctionnels
Généralités
Motifs Courants
5
Objets fonctionnels
Lambda
En argument
Généralités
Motifs
En retour
Généralités
Motifs
Comme objets
2/38
Définitions niveau fonction
Définitions simples
Programmation
Fonctionnelle
Didier Verna
E PITA
Lisp
Haskell
( defun backwards ( l s t )
( reverse l s t ) )
backwards : : [ a ] −> [ a ]
backwards xs = reverse xs
Généralités
Lambda
En argument
Scheme
Généralités
Motifs
En retour
( define ( backwards l s t )
( reverse l s t ) )
Généralités
Motifs
Comme objets
Lisp
Haskell
( s e t f ( symbol−function ’ backwards )
# ’ reverse )
backwards : : [ a ] −> [ a ]
backwards = reverse
Scheme
( define backwards reverse )
4/38
Lisp : Symboles
Lisp-1 (Scheme) vs. Lisp-2 (Common Lisp)
Programmation
Fonctionnelle
Didier Verna
E PITA
Généralités
Lambda
En argument
Généralités
Motifs
En retour
Généralités
Motifs
Comme objets
Les symboles contiennent
des propriétés, dont une
valeur et une valeur
fonctionnelle.
Un symbole peut dénoter à
la fois une variable et une
fonction (espaces de noms
distincts).
defun et defparameter
ne sont pas indispensables
(macros).
5/38
foobar
.....
Valeur
Valeur fonctionnelle
( defparameter ∗f o o∗ 3 )
( defun ∗f o o∗ ( x ) (∗ 2 x ) )
( s e t f ( symbol−value ’∗ f o o ∗) 3 )
( s e t f ( symbol−function ’∗ f o o ∗)
( lambda ( x ) (∗ 2 x ) ) )
Lisp : Valeurs vs. valeurs fonctionnelles
A PI pour l’appel de fonction
Programmation
Fonctionnelle
Fonction function, read-macro #’
Didier Verna
E PITA
( assert ( eq ( f u n c t i o n +) # ’ + ) )
Généralités
Lambda
Fonction (funcall func &rest args)
En argument
Généralités
Motifs
( f u n c a l l # ’+ 1 2 3 4 5 )
En retour
Généralités
Motifs
Fonction (apply func arg &rest args)
Comme objets
( apply # ’+ 1 2 3 ’ ( 4 5 ) )
6/38
Lisp : Fonctions variadiques
De l’influence de la syntaxe. . .
Programmation
Fonctionnelle
Didier Verna
E PITA
Généralités
Un appel de fonction Lisp est syntaxiquement clos :
(func arg1 arg2 ...)
Fonctions variadiques :
Lambda
En argument
Généralités
( defun m k l i s t ( head &r e s t t a i l )
( cons head t a i l ) )
; ; ( mklist ’a ’b ’c)
Motifs
En retour
Généralités
Motifs
Comme objets
( defun msg ( s t r & o p t i o n a l ( p r e f i x "error: " ) p o s t f i x )
( concatenate ’ s t r i n g p r e f i x s t r p o s t f i x ) )
; ; ( msg " h e l l o " n i l " ! " )
( defun msg∗ ( s t r &key p r e f i x ( p o s t f i x "." ) )
( concatenate ’ s t r i n g p r e f i x s t r p o s t f i x ) )
; ; ( msg∗ " h e l l o " : p r e f i x "Me: " )
Plus &-combinaisons . . .
7/38
Haskell : Application partielle et coupure
De l’influence de la syntaxe. . .
Programmation
Fonctionnelle
Didier Verna
E PITA
m u l t i p l y : : F l o a t −> F l o a t −> F l o a t
multiply a b = a ∗ b
−− m u l t i p l y a b
Généralités
Lambda
En argument
Généralités
Motifs
En retour
Généralités
Motifs
Comme objets
-> est associatif à droite
Float -> (Float -> Float)
L’application est associative à gauche :
multiply 2 5 ⇔ (multiply 2) 5
Curryfication : Les fonctions Haskell sont unaires
I
I
8/38
Application partielle :
multiply 2 :: Float -> Float
Coupure d’opérateur :
(+2) (>3) (3:) ("error: "++) etc.
Fonctions anonymes : rappel
Des littéraux comme les autres. . .
Programmation
Fonctionnelle
Didier Verna
E PITA
Généralités
Possibilité de ne pas nommer les fonctions :
Lisp
Haskell
( lambda ( x ) (∗ 2 x ) )
\ x −> 2 ∗ x
Lambda
Utilisation directe (littérale) :
au même titre que les int, les chaînes de caractères
etc.
En argument
Généralités
Motifs
En retour
Généralités
Motifs
Lisp
Haskell
( ( lambda ( x ) (∗ 2 x ) ) 4 )
( \ x −> 2 ∗ x ) 4
Comme objets
10/38
Contextes locaux et fonctions anonymes
Équivalence conceptuelle
Programmation
Fonctionnelle
Didier Verna
E PITA
Généralités
Lambda
let ouvre un bloc explicite
Les fonctions ouvrent des blocs implicites
Grâces aux fonctions anonymes, let est inutile
Lisp
Lisp
( defun f ( x )
( l e t ( ( a (∗ x x ) )
( b (+ (∗ x x ) 1 ) ) )
(+ ( / a b ) ( / b a ) ) ) )
( defun f ( x )
( ( lambda ( a b )
(+ ( / a b ) ( / b a ) ) )
(∗ x x ) (+ (∗ x x ) 1 ) ) )
En argument
Généralités
Motifs
En retour
Généralités
Motifs
Comme objets
Remarques :
I
I
11/38
Cela explique pourquoi les références croisées sont
impossibles dans un let.
Modèle inapplicable à Haskell.
Application à let*
Imbrication
Programmation
Fonctionnelle
let* se comporte comme des let imbriqués.
Didier Verna
E PITA
Lisp
Généralités
Lambda
En argument
Généralités
( defun f ( x )
( l e t ∗ ( ( a (∗ x x ) )
( b (+ a 1 ) ) )
(+ ( / a b ) ( / b a ) ) ) )
Motifs
En retour
Généralités
Motifs
Comme objets
12/38
Lisp
Lisp
( defun f ( x )
( l e t ( ( a (∗ x x ) ) )
( l e t ( ( b (+ a 1 ) ) )
(+ ( / a b ) ( / b a ) ) ) ) )
( defun f ( x )
( ( lambda ( a )
( ( lambda ( b )
(+ ( / a b ) ( / b a ) ) )
(+ a 1 ) ) )
(∗ x x ) ) )
Motivation (1)
Des formes communes d’abstraction
Programmation
Fonctionnelle
b
∑ f (n) = f (a) + . . . + f (b)
Didier Verna
E PITA
Généralités
n=a
Lisp
Haskell
( defun s i n t ( a b )
( i f (> a b)
0
(+ a ( s i n t (1+ a ) b ) ) ) )
s i n t : : I n t −> I n t −> I n t
sint a b
| a > b = 0
| otherwise = a + s i n t ( a +1) b
( defun ssq ( a b )
( i f (> a b)
0
(+ ( sq a ) ( ssq (1+ a ) b ) ) ) )
ssq : : I n t −> I n t −> I n t
ssq a b
| a > b = 0
| otherwise = sq a + ssq ( a +1) b
( defun s p i ( a b )
( i f (> a b)
0
(+ ( / 1 . 0 (∗ a (+ a 2 ) ) )
( s p i (+ a 4 ) b ) ) ) )
s p i : : I n t −> I n t −> F l o a t
spi a b
| a > b = 0
| otherwise
= 1 . 0 / f r o m I n t e g r a l ( a ∗ a +2)
+ s p i ( a +4) b
Lambda
En argument
Généralités
Motifs
En retour
Généralités
Motifs
Comme objets
14/38
Motivation (2)
Des formes communes d’abstraction
Programmation
Fonctionnelle
Didier Verna
E PITA
Généralités
Lambda
En argument
Lisp
Haskell
( defun sigma ( a b term n e x t )
( i f (> a b)
0
(+ ( f u n c a l l term a )
( sigma ( f u n c a l l n e x t a ) b
term n e x t ) ) ) )
sigma : : Num a => I n t −> I n t
−> ( I n t −> a ) −> ( I n t −> I n t ) −> a
sigma a b term next
| a > b = 0
| otherwise
= term a + sigma ( next a ) b
term next
( defun s i n t ( a b )
( f u n c a l l # ’ sigma a b
# ’ identity # ’1+))
s i n t : : I n t −> I n t −> I n t
s i n t a b = sigma a b i d ( + 1 )
Généralités
Motifs
En retour
Généralités
Motifs
Comme objets
( defun ssq ( a b )
( f u n c a l l # ’ sigma a b
# ’ sq # ’ 1 + ) )
( defun pi−term ( a )
( / 1 . 0 (∗ a (+ a 2 ) ) ) )
( defun pi−step ( a )
(+ a 4 ) )
( defun s p i ( a b )
( f u n c a l l # ’ sigma a b
# ’ pi−term # ’ pi−step ) )
15/38
ssq : : I n t −> I n t −> I n t
ssq a b = sigma sq ( + 1 )
p i t e r m : : I n t −> F l o a t
p i t e r m a = 1 . 0 / f r o m I n t e g r a l ( a ∗ a +2)
p i s t e p : : I n t −> I n t
pistep a = a + 4
s p i : : I n t −> I n t −> F l o a t
s p i a b = sigma a b p i t e r m p i s t e p
Mapping
1er motif incontournable
Programmation
Fonctionnelle
Didier Verna
E PITA
Généralités
Lambda
En argument
Généralités
Motif :
Lisp
Haskell
( defun double ( l s t )
( i f ( null l s t )
nil
( cons (∗ 2 ( c a r l s t ) )
( double ( c d r l s t ) ) ) ) )
double1 , double2 : : [ I n t ] −> [ I n t ]
double1 [ ] = [ ]
double1 ( x : xs ) = 2∗x : double1 xs
double2 xs = [ 2∗ e l t | e l t <− xs ]
Motifs
En retour
Généralités
Motifs
Comme objets
Lisp : (mapcar func list &rest lists)
Haskell : map :: (a -> b) -> [a] -> [b]
Exemples :
16/38
Lisp
Haskell
( defun double ( l s t )
( mapcar ( lambda ( x ) (∗ 2 x ) )
lst ))
double : : [ I n t ] −> [ I n t ]
double = map ( ∗ 2 )
Mapping généralisé
Sur plusieurs listes
Programmation
Fonctionnelle
Didier Verna
E PITA
Généralités
Lambda
En argument
Généralités
Motif :
Lisp
Haskell
( defun l i s t + ( l 1 l 2 )
( i f ( or ( n u l l l 1 ) ( n u l l l 2 ) )
nil
( cons (+ ( c a r l 1 ) ( c a r l 2 ) )
( l i s t + ( cdr l 1 ) ( cdr l 2 ) ) ) ) )
( ! + ) : : [ I n t ] −> [ I n t ] −> [ I n t ]
( ! + ) ( x : xs ) ( y : ys ) = ( x + y )
: xs ! + ys
(!+) _
_
= []
Motifs
En retour
Généralités
Motifs
Comme objets
Lisp : mapcar variadique.
Haskell :
zipWith :: (a -> b -> c) -> [a] -> [b]
-> [c]
Exemples :
17/38
Lisp
Haskell
( defun l i s t + ( l 1 l 2 )
( mapcar # ’+ l 1 l 2 ) )
( ! + ) : : [ I n t ] −> [ I n t ] −> [ I n t ]
( ! + ) = zipWith ( + )
Filtrage / Élimination
2e motif incontournable
Programmation
Fonctionnelle
Didier Verna
E PITA
Généralités
Lambda
En argument
Généralités
Motifs
En retour
Motif :
Lisp
Haskell
( defun p s t ( l )
( cond ( ( n u l l l )
nil )
(( > ( car l ) 0)
( cons ( c a r l )
( pst ( cdr l ) ) ) )
(t
( pst ( cdr l ) ) ) ) )
pst1 , p s t 2 : : [ I n t ] −> [ I n t ]
pst1 [ ] = [ ]
p s t 1 ( x : xs )
| x > 0 = x : p s t 1 xs
| otherwise = p s t 1 xs
p s t 2 xs = [ e | e <− xs , e > 0 ]
Généralités
Motifs
Comme objets
18/38
Lisp : (remove-if[-not] pred list &key ...)
Haskell :
filter :: (a -> Bool) -> [a] -> [a]
Exemples :
Lisp
Haskell
( defun p s t ( l )
( remove−if ( lambda ( x ) ( < x 0 ) )
l ))
p s t : : [ I n t ] −> [ I n t ]
p s t = f i l t e r ( >0)
Folding / Réduction
3e motif incontournable
Programmation
Fonctionnelle
Didier Verna
E PITA
Généralités
Lambda
En argument
Généralités
Motifs
Motif :
Lisp
Haskell
( defun l i s t s u m ( l )
( cond ( ( n u l l l )
( e r r o r "empty list" ) )
( ( null ( cdr l ) )
( car l ) )
( t (+ ( c a r l )
( l i s t s u m ( cdr l ) ) ) ) ) )
l i s t s u m : : [ I n t ] −> I n t
listsum [ x ] = x
l i s t s u m ( x : xs ) = x + l i s t s u m xs
En retour
Généralités
Motifs
Comme objets
Lisp : (reduce func seq &key ...)
Haskell :
foldr1 :: (a -> a -> a) -> [a] -> a
Exemples :
19/38
Lisp
Haskell
( defun l i s t s u m ( l )
( reduce # ’+ l ) )
l i s t s u m : : [ I n t ] −> I n t
listsum = foldr1 (+)
Folding généralisé
Valeur de retour pour la liste vide
Programmation
Fonctionnelle
Didier Verna
E PITA
Lisp : clé :initial-value de reduce
Remarque : (+) => 0, (*) => 1
Haskell : foldr
Généralités
Lambda
En argument
f o l d r : : ( a −> b −> b ) −> b −> [ a ] −> b
foldr f s [ ]
= s
f o l d r f s ( x : xs ) = f x ( f o l d r f s xs )
Généralités
Motifs
En retour
Généralités
Motifs
Comme objets
20/38
Folding généralisé et récursion primitive :
Beaucoup de fonctions primitive-récursives peuvent
s’exprimer comme un fold.
Lisp
Haskell
( defun snoc ( e l t l s t )
( append l s t ( l i s t e l t ) ) )
snoc : : a −> [ a ] −> [ a ]
snoc x xs = xs ++ [ x ]
( defun r e v ( l s t )
( reduce # ’ snoc l s t
: from−end t
: initial−value nil ))
r e v : : [ a ] −> [ a ]
r e v = f o l d r snoc [ ]
Recherche / indexation
Programmation
Fonctionnelle
Didier Verna
E PITA
Recherche :
I
Généralités
Lambda
I
En argument
Généralités
Motifs
En retour
Indexation :
I
Généralités
Motifs
Comme objets
21/38
Lisp : (member-if[-not] pred lst &key ...)
(réservé aux listes),
(find-if[-not] pred seq &key ...)
Haskell :
find :: (a -> Bool) -> [a] -> Maybe a
I
Lisp :
(position-if[-not] pred seq &key ...)
Haskell :
findIndex :: (a -> Bool) -> [a] -> Maybe Int
Extraction
Programmation
Fonctionnelle
Didier Verna
E PITA
Généralités
Lambda
En argument
Généralités
Motif :
Haskell
getWord : : S t r i n g −> S t r i n g
getWord [ ] = [ ]
getWord ( x : xs )
| x == ’ ’ = [ ]
| otherwise = x : getWord xs
Motifs
En retour
Généralités
Motifs
Comme objets
Haskell :
takeWhile :: (a -> Bool) -> [a] -> [a]
dropWhile :: (a -> Bool) -> [a] -> [a]
Exemples :
Haskell
getWord : : S t r i n g −> S t r i n g
getWord s t r = dropWhile ( \ x −> x == ’
22/38
’) str
Divers
Comme d’été
Programmation
Fonctionnelle
Didier Verna
E PITA
Généralités
Prédicats :
I
I
Lambda
En argument
Généralités
Motifs
Lisp : Fonctions
(every|some pred seq &rest seqs)
Haskell : Fonctions
all|any :: (a -> Bool) -> [a] -> Bool
Tri :
I
En retour
Généralités
Lisp : Fonction (sort seq pred &key ...)
Attention : sort est destructif !
Motifs
Comme objets
( setf foo ( sort # ’ > foo ) )
I
Haskell : Fonctions
sort :: Ord a => [a] -> [a]
sortBy :: (a -> a -> Ordering) -> [a] -> [a]
23/38
Motivation
Une question d’orthogonalité
Programmation
Fonctionnelle
Fonctions complémentaires de Lisp :
Didier Verna
E PITA
Généralités
( remove−if−not # ’ pred l s t )
( remove−if ( lambda ( x ) ( not ( pred x ) ) )
( remove−if ( complement # ’ pred ) l s t )
lst )
Lambda
En argument
Généralités
Motifs
I
Fonction complement: -50% de prédicats
(obsolescence des formes en -not)
En retour
Généralités
Motifs
Macro setf : accesseurs en tant que lvalues. . .
Comme objets
( defvar f o o ’ ( 1 2 3 4 5 ) )
( nth 2 f o o ) ; ; => 3
( s e t f ( nth 2 f o o ) 0 ) ; ; s e t n t h doesn ’ t e x i s t
f o o ; ; => ( 1 2 0 4 5 )
25/38
Lisp : Retours fonctionnels et scoping
Problème de la « capture » de variables
Programmation
Fonctionnelle
Didier Verna
E PITA
Généralités
Lambda
En argument
Fonctions constantes :
Fonctions à la demande :
( defun +/− ( which_one )
( i f (= which_one 0 )
# ’+
# ’−))
( defun make−adder ( n )
# ’ ( lambda ( x )
(+ x n ) ) )
; ; ( f u n c a l l ( make−adder 3 ) 1 )
; ; ( f u n c a l l (+/− 0 ) 4 2 )
Généralités
Motifs
En retour
Généralités
Motifs
Comme objets
Scoping dynamique : retour fonctionnel limité aux
fonctions constantes
Scoping lexical : retour de fonctions créés à la
demande en toute sécurité
( defun complement ( f n )
# ’ ( lambda (& r e s t args )
( not ( apply f n args ) ) ) )
Remarque : retour fonctionnel et fermetures lexicales =
coût principal d’implémentation du 1er ordre.
26/38
Haskell : Rappels
Retours fonctionnels cachés
Programmation
Fonctionnelle
Didier Verna
E PITA
Généralités
Coupure d’opérateur / application partielle :
(+3) :: Int -> Int
Définition niveau fonction :
Lambda
En argument
Généralités
Motifs
En retour
Généralités
Motifs
Comme objets
27/38
adder : : I n t −> ( I n t −> I n t )
adder n = \ x −> x + n
adder : : I n t −> ( I n t −> I n t )
adder n = add
where add x = x + n
−− ( adder 3 ) 1
−− ( adder 3 ) 1
Composition de fonctions
Programmation
Fonctionnelle
Didier Verna
E PITA
Lisp
Haskell
( defun i s o d d ( n )
( not ( evenp n ) ) )
i s o d d : : I n t e g e r −> Bool
i s o d d n = not ( even n )
( defun compose (& r e s t f n s )
; ; Not t r i v i a l . Only t h e f i r s t
; ; f u n c t i o n can be v a r i a d i c .
)
i s o d d : : I n t e g e r −> Bool
i s o d d = not . even
Généralités
Lambda
En argument
Généralités
Motifs
En retour
Généralités
Motifs
( defun i s o d d ( n )
( compose # ’ not # ’ evenp ) )
Comme objets
complement : cas particulier de compose
Type Haskell :
(.) :: (b -> c) -> (a -> b) -> (a -> c)
Associativité de . :
f . (g . h) = (f . g) . h = f . g .h
Précédence Haskell : f . g x = f . (g x)
28/38
Composition itérative
f n (x)
Programmation
Fonctionnelle
Didier Verna
E PITA
Généralités
Lambda
En argument
Vision récursive :
Lisp
Haskell
( defun i t e r ( n f )
( i f ( > n 0)
( compose f ( i t e r (1− n ) f ) )
# ’ identity ))
i t e r : : I n t −> ( a −> a ) −> ( a −> a )
iter n f
| n > 0 = f . i t e r ( n − 1) f
| otherwise = i d
Généralités
Motifs
Vision fold’esque :
En retour
Généralités
Motifs
Comme objets
( defun i t e r ( n f )
( reduce # ’ compose ( make−list n : i n i t i a l − e l e m e n t f )
: initial−value # ’ identity
: from−end t ) )
i t e r : : I n t −> ( a −> a ) −> ( a −> a )
i t e r n f = foldr ( . ) id ( replicate n f )
29/38
(Dé) Curryfication
Arité des fonctions
Programmation
Fonctionnelle
Didier Verna
E PITA
Généralités
Formes (dé) curryfiée :
Haskell
Haskell
m u l t i p l y : : I n t −> I n t −> I n t
multiply a b = a ∗ b
m u l t i p l y : : ( I n t , I n t ) −> I n t
multiply (a, b) = a ∗ b
Lambda
En argument
Généralités
Haskell : (Dé) Curryfication
Motifs
En retour
Généralités
Motifs
Comme objets
30/38
curry : : ( ( a , b ) −> c )
−> ( a −> b −> c )
curry g x y = g ( x , y )
uncurry : : ( a −> b −> c )
−> ( ( a , b ) −> c )
uncurry g ( x , y ) = g x y
Lisp : Currification partielle
Lisp
Lisp
( defun c u r r y ( f n &r e s t args )
# ’ ( lambda (& r e s t args2 )
( apply f n
( append args args2 ) ) ) )
( defun r c u r r y ( f n &r e s t args )
# ’ ( lambda (& r e s t args2 )
( apply f n
( append args2 args ) ) ) )
Récurseurs de listes
Version initiale
Programmation
Fonctionnelle
Didier Verna
E PITA
Généralités
Lambda
En argument
Généralités
Motif :
( defun l e n ( l s t )
( i f ( null l s t )
0
(1+ ( l e n ( c d r l s t ) ) ) ) )
l e n : : [ a ] −> I n t
len [ ] = 0
l e n ( x : xs ) = 1 + l e n xs
Récurseur :
Motifs
En retour
Généralités
Motifs
Comme objets
( defun l r e c ( f n v a l )
( labels ( ( s e l f ( l s t )
( i f ( null l s t )
val
( funcall fn ( s e l f ( cdr l s t ) ) ) ) ) )
#’ self ))
; ; ( f u n c a l l ( l r e c # ’1+ 0 ) ’ ( 1 2 3 4 5 ) ) => 5
l r e c : : ( a −> a ) −> a −> ( [ b ] −> a )
lrec fn val = le t s e l f [ ] = val
s e l f ( x : xs ) = f n ( s e l f xs )
in s e l f
−− ( l r e c ( 1 + ) 0 ) [ 1 , 2 , 3 , 4 , 5 ] => 5
31/38
Récurseurs de listes
Version générale
Programmation
Fonctionnelle
Didier Verna
E PITA
Généralités
Lambda
En argument
Généralités
Motifs
Motif :
( defun every1 ( p l s t )
( i f ( null l s t )
t
( and ( f u n c a l l p ( c a r l s t ) )
( every1 p
( cdr l s t ) ) ) ) )
a l l 1 : : ( a −> Bool ) −> [ a ] −> Bool
a l l 1 _ [ ] = True
a l l 1 p ( x : xs ) = p x
&& a l l 1 p xs
Récurseur :
En retour
Généralités
Motifs
Comme objets
32/38
( defun l r e c 1 ( f n v a l )
( labels ( ( s e l f ( l s t )
( i f ( null l s t )
val
( funcall fn ( car l s t )
# ’ ( lambda ( )
( s e l f ( cdr l s t ) ) ) ) ) ) )
#’ self ))
l r e c 1 : : ( a −> b −> b ) −> b −> ( [ a ] −> b )
lrec1 fn val = let s e l f [ ] = val
s e l f ( x : xs ) = f n x ( s e l f xs )
in s e l f
Application
Récurseurs communs
Programmation
Fonctionnelle
Didier Verna
E PITA
Généralités
Lambda
En argument
Généralités
Motifs
En retour
Généralités
; ; every f o r some PREDicate
( l r e c 1 # ’ ( lambda ( e l t c n t ) ( and (PRED e l t ) ( f u n c a l l c n t ) ) ) t )
; ; some f o r some PREDicate
( l r e c 1 # ’ ( lambda ( e l t c n t ) ( or
(PRED e l t ) ( f u n c a l l c n t ) ) )
nil )
; ; f i n d − i f f o r some PREDicate
( l r e c 1 # ’ ( lambda ( e l t c n t ) ( i f (PRED e l t ) e l t ( f u n c a l l c n t ) ) )
; ; remove−if−not f o r some PREDicate
( l r e c 1 # ’ ( lambda ( e l t c n t ) ( i f (PRED e l t )
( cons e l t ( f u n c a l l c n t ) )
( funcall cnt ) ) ) n i l )
Motifs
Comme objets
−− a l l f o r some PREDicate
l r e c 1 ( \ e l t c n t −> PRED e l t && c n t ) True
−− any f o r some PREDicate
l r e c 1 ( \ e l t c n t −> PRED e l t
| | c n t ) False
−− f i n d f o r some PREDicate
l r e c 1 ( \ e l t c n t −> i f PRED e l t then Just e l t else c n t ) Nothing
−− f i l t e r f o r some PREDicate
l r e c 1 ( \ e l t c n t −> i f PRED e l t then ( e l t : c n t ) else c n t ) [ ]
33/38
nil )
Lisp : Récurseurs d’arbres
Représentation par liste hétérogène
Programmation
Fonctionnelle
Didier Verna
E PITA
Généralités
Lambda
En argument
Motifs :
( defun l e a v e s ( t r e e )
( i f ( atom t r e e )
1
(+ ( l e a v e s ( c a r t r e e ) )
( or ( i f ( c d r t r e e ) ( l e a v e s ( c d r t r e e ) ) )
1))))
Généralités
Motifs
En retour
Généralités
Motifs
Comme objets
34/38
( defun f l a t t e n ( t r e e )
( i f ( atom t r e e )
( l i s t tree )
( append ( f l a t t e n ( c a r t r e e ) )
( i f ( cdr t r e e ) ( f l a t t e n ( cdr t r e e ) ) ) ) ) )
Application
leaves et flatten
Programmation
Fonctionnelle
Didier Verna
E PITA
Généralités
Lambda
En argument
Généralités
Motifs
En retour
Généralités
Récurseur :
( defun t r e c ( f n v a l )
( labels ( ( s e l f ( tree )
( i f ( atom t r e e )
( funcall val tree )
( funcall fn
# ’ ( lambda ( )
( s e l f ( car t r e e ) ) )
# ’ ( lambda ( )
( i f ( cdr t r e e )
( s e l f ( cdr t r e e ) ) ) ) ) ) ) )
#’ self ))
Motifs
Comme objets
Exemples :
; ; leaves
( t r e c # ’ ( lambda ( l c n t r c n t )
(+ ( f u n c a l l l c n t ) ( or ( f u n c a l l r c n t ) 1 ) ) )
# ’ ( lambda ( e l t )
1))
35/38
; ; flatten
( t r e c # ’ ( lambda ( l c n t r c n t )
( append ( f u n c a l l l c n t ) ( f u n c a l l r c n t ) ) )
#’ list )
Qu’appelle t’on « donnée » ?
Programmation
Fonctionnelle
Didier Verna
E PITA
En général :
I
I
Généralités
Lambda
En argument
Généralités
Motifs
En retour
Généralités
Motifs
Comme objets
37/38
Représentation : structures de données
Manipulation : fonctions sur les données
Abstraction de données / interface :
I
I
I
Constructeurs, accesseurs et manipulateurs
Conditions d’ inter-fonctionnement
Toute implémentation doit satisfaire ces conditions
Conclusion :
I
I
Distinguer l’interface de son implémentation
Toute implémentation peut convenir, y compris une
implémentation fonctionnelle (fermetures lexicales) au
lieu de structures de données
Lisp : Listes fonctionnelles
Application
Programmation
Fonctionnelle
Didier Verna
E PITA
Généralités
Lambda
En argument
Généralités
Motifs
En retour
Généralités
( defun f c o n s ( c a r c d r )
( l a b e l s ( ( d i s p a t c h ( arg )
( cond ( ( = 0 arg )
car )
(t
cdr ) ) ) )
# ’ dispatch ) )
( defun f c a r ( o b j )
( funcall obj 0))
( defun f c d r ( o b j )
( funcall obj 1))
Motifs
Comme objets
Les fonctions du 1er ordre (fermetures lexicales)
permettent la représentation de données complexes.
L’implémentation fonctionnelle utilise une stratégie
d’« envoi de message » (message passing).
38/38

Documents pareils