MEER PREDIKATEN EN CONDITIES

Meer predikaten

Gelijkheidspredikaten

De volledige verzameling voorgedefinieerde predikaten is de volgende:

> (string=? "aap" "AaP")
#f
> (string=? "" "")
#t
> (= 1 1)
#t
> (= 1.0 1)
#t
> (eqv? 1.0 1)
#f
> (eqv? 5 5)
#t
> (equal? 1.0 1)
#f
> (eq? 'aap 'aap)
#t
> (eq? 'a 'b)
#f
> (let* ((x 'a)
         (y x))
     (eq? x y))
#t
> (eqv? 'aap 'aap)
#t
> (eqv? '(1 2 3) '(1 2 3))
#f
> (equal? '(1 2 3) '(1 2 3))
#t
> (equal? '(cons 1 (cons (list 2 5) (cons 3 ()))) '(1 (2 5) 3))
#f
> (equal? (cons 1 (cons (list 2 5) (cons 3 ()))) '(1 (2 5) 3))
#t

Gebruik steeds =, CHAR= en STRING= wanneer zekerheid bestaat dat de te vergelijken objecten respectievelijk getallen, characters of strings zijn. In andere gevallen is EQV? aangewezen, tenzij het om lijsten gaat die recursief vergeleken moeten worden; gebruik dan EQUAL?.

Member

Om te beslissen of een Lisp object gelijk is aan iets wat in de lijst zit moet natuurlijk gebruik worden gemaakt van een gelijkheidspredikaat. Het gelijkheidspredikaat van MEMBER is EQUAL?. De predikaten MEMQ en MEMV gebruiken respctievelijk de gelijkheidspredikaten EQ? en EQV?.

> (member '(appel) '((peer)(appel)(pruim)))
((appel) (pruim))
> (memq '(appel) '((peer)(appel)(pruim)))
#f

Associatielijsten

De associatielijst (a-list) is een veelgebruikte datastructuur waar gelijkheidspredikaten een belangrijke rol in spelen. Een a-list is een lijst van sublijsten (meestal pairs). Bij elk van die sublijsten speelt de CAR de rol van zoeksleutel, en de CDR de rol van datum (gegeven). We kunnen gegevens uit de a-list halen met de functie (ASSOC expressie lijst) die als eerste argument een zoeksleutel neemt, en als tweede argument een a-list. De functie retourneert de eerste sublijst in a-list die een CAR heeft die gelijk is aan de zoeksleutel. Als zo een sublijst niet wordt gevonden is het resultaat #f. Aangezien de functie alleen de eerste sublijst opleveren waarin de zoeksleutel gevonden werd, kan nieuw toegevoegde informatie vooraan in de a-list, de bestaande informatie ontoegankelijk maken (schaduwen). Het gelijkheidspredikaat van ASSOC is EQUAL?. De functies ASSQ en ASSV gebruiken respectievelijk de gelijkheidspredikaten EQ? en EQV?.

(define *lexicon*
  '((appel . n)(peer . n)(de . det)(het . det)(jongen . n)(eet . v)))
((APPEL . N) (PEER . N) (DE . DET) (HET . DET) (JONGEN . N) (EET . V))
> (assoc 'de *lexicon*)
(DE . DET)
> (set! *lexicon* (cons '(de . kwantor) *lexicon*))
((DE . KWANTOR) (APPEL . N) (PEER . N) (DE . DET) (HET . DET) 
 (JONGEN . N) (EET . V))
> (assoc 'de *lexicon*)
(DE . KWANTOR)
> (assoc 'foo *lexicon*)
#f

Data-type predikaten

Voor de meeste types in LISP bestaat er een predikaat om na te gaan of een argument een bepaald type heeft:

(SYMBOL? expressie); (NUMBER? expressie); (COMPLEX? expressie); (REAL? expressie); (RATIONAL? expressie); (INTEGER? expressie); (PAIR? expressie); (LIST? expressie); (NULL? expressie) (lege lijst?); (STRING? expressie); (BOOLEAN? expressie); (CHAR? expressie) (character?); (PROCEDURE? expressie).

Mathematische predikaten

Er bestaan ook specifiek numerieke predikaten die nuttig zijn wanneer met getallen moet worden gewerkt. De belangrijkste zijn ZERO?, POSITIVE?, NEGATIVE?, EVEN?, ODD?, >, < waarvan we de werking met enkele voorbeelden duidelijk maken. EVEN? en ODD? werken uiteraard alleen met gehele getallen als argument.

> (zero? 12)
#f
> (zero? 0.0)
#t
> (positive? (abs -4))
#t
> (negative? -3)
#t
> (even? (expt 2 3))
#t
> (odd? (gcd 4 8 12))
#f
> (even? 2.0)
ERROR: even?: Wrong type in arg1 2.0
> (< 2 3 4)
#t
> (< 1 2 3 5 4 6 7 8 9)
#f
> (> 3 2 2 1)
#f
> (>= 3 2 2 1)
#t

String en character predikaten

Er zijn een aantal primitieve predikaten die telkens twee characters of twee strings als argumenten nemen, en die de alfanumerieke volgorde van instanties van deze datastructuren vergelijken. Deze predikaten zijn CHAR? CHAR<=?, CHAR>=?. Daarnaast bestaan voor characters ook nog de primitieve predikaten CHAR-ALPHABETIC?, CHAR-NUMERIC?, CHAR-WHITESPACE?, CHAR-UPPER-CASE?, en CHAR-LOWER-CASE? met een voor de hand liggende semantiek.

Meer conditionele expressies

Behalve IF zijn er twee belangrijke conditionele expressies die worden gebruikt om de flow of control van een programma te bepalen: COND en CASE.

> (define welk-type
    (lambda (x)
      (cond 
        ((number? x) 'getal)
        ((symbol? x) 'symbool)
        ((list? x) 'lijst)
        (else 'ik-geef-het-op))))
WELK-TYPE
> (welk-type 'appel)
SYMBOOL
> (welk-type "appel")
IK-GEEF-HET-OP
> (define lekker
    (lambda (x)
      (case x
        ((tomaat wortel erwt andijvie) 'lekkere_groente)
        ((tijm laurier peper) 'lekkere_kruiden)
        ((appel citroen peer banaan kiwi) 'lekker_fruit)
        (else 'Dat_lust_ik_niet))))
LEKKER
> (lekker 'peper)
LEKKERE_KRUIDEN
> (lekker 'rabarber)
DAT_LUST_IK_NIET

Walter Daelemans <Walter.Daelemans@kub.nl>
Last modified: Tue Mar 18 14:30:35 1997