Précédent Index Suivant

Notion de semi-prédicat

 

 
Problématique  
On peut définir le prédicat avez-vous? qui, étant donnés un prédicat et une liste, rend vrai si, et seulement si, il existe une occurrence dans la liste donnée qui vérifie le prédicat donné. Par exemple:
 
(avez-vous? odd? (list 4 2 1 3)) -> #T
 
(avez-vous? odd? (list 4 2)) -> #F
 

 
Cette fonction se définit très facilement (ce n'est qu'un exercice de révision):
 
;;; avez-vous? : (alpha -> bool) * LISTE[alpha] -> bool 
;;; (avez-vous? test? L) rend vrai ssi il existe un élément de la  
;;; liste «L» qui vérifie «test?» 
(define (avez-vous? test? L)
  (if (pair? L)
      (if (test? (car L))
          #t
          (avez-vous? test? (cdr L)))
      #f))
 

 
Semi-prédicat  
La fonction précédente fait un peu penser au gag de celui qui répond « oui » lorsqu'on lui demande « avez-vous l'heure? ». En fait, on peut vouloir définir la fonction val qui, étant donnés un prédicat et une liste,  
Par exemple:
 
(val odd? (list 4 2 1 3)) -> 1
 
(val odd? (list 4 2)) -> #F
 

 
Cette fonction, qui rend #f dans certains cas et une valeur non booléenne dans d'autres cas, est appellée un semi-prédicat. Sa définition peut être:
 
;;; val : (alpha -> bool) * LISTE[alpha] -> alpha + #f 
;;; (val test? L) rend la valeur du premier élément de «L» qui vérifie «test?» 
;;; s'il existe un tel élément et rend #f sinon. 
(define (val test? L)
  (if (pair? L)
      (if (test? (car L))
          (car L)
          (val test? (cdr L)))
      #f))
 

 
Noter la signature de la fonction avec son « + #f » qui indique un semi-prédicat. Noter aussi que, classiquement, contrairement aux prédicats, les noms des semi-prédicats ne finissent pas par un point d'interrogation.
 
Un autre exemple: member est une primitive de Scheme (cf. carte de référence) dont la spécification est:  
;;; member : alpha * LISTE[alpha] -> LISTE[alpha] + #f  
;;; (member v L) rend le suffixe de «L» débutant par la première occurrence de «v» 
;;; ou #f si «v» n'apparaît pas dans «L». 
 

 
Exemples d'application:
 
(member 3 (list 2 3 1 3 2)) -> (3 1 3 2)
 
(member 1 (list 2 3 1)) -> (1)

 
(member 3 (list 2 1)) -> #F
 

 
La définition pouvant être:  
(define (member v L)
  (if (pair? L)
      (if (equal? v (car L))
          L
          (member v  (cdr L)))
      #f))
 

 
Alternative et semi-prédicat  
En fait, dans une alternative, toute condition qui n'a pas la valeur #f a une valeur de vérité Vrai.
 
Ainsi, en utilisant la fonction val que nous avons définie plus haut:
 
(if (val odd? (list 4 2 1 3))
    "il existe une valeur impaire"
    "il n'existe pas de valeur impaire")

--> il existe une valeur impaire  

 
et
 
(if (val odd? (list 4 2))
    "il existe une valeur impaire"
    "il n'existe pas de valeur impaire")

--> il n'existe pas de valeur impaire  

 
Un autre exemple  
Nous voudrions définir le semi-prédicat index qui, étant donnés un élément et une liste, rend l'index de la première occurrence de cet élément dans la liste s'il existe un tel élément et rend #f sinon (dans une liste, l'index de son premier élément est égal à 1, l'index de son deuxième élément est égal à 2...). Par exemple:
 
(index 2 (list 1 2 3)) -> 2
 
(index 4 (list 1 2 3)) -> #F
 

 
Cette fonction peut être définie par:  
;;; index : alpha * LISTE[alpha] -> nat + #f 
;;; (index elm L) rend l'index de la première occurrence de «elm» dans «L»  
;;; s'il en existe une (l'index du premier élément d'une liste est égal à 1,  
;;; du deuxième élément est égal à 2...) ; rend #f sinon. 
(define (index elm L)
  (if (pair? L)
      (if (equal? elm (car L))
          1
          (let ((index-cdr-L (index elm (cdr L))))
            (if index-cdr-L
                (+ 1 index-cdr-L)
                #f)))
      #f))
 

 
Noter l'utilisation de la variable index-cdr-L:  



Auteur(s): titou@ufr-info-p6.jussieu.fr.Mainteneur de la page: titou@ufr-info-p6.jussieu.fr.
 

Précédent Index Suivant