Functies

De commando's uit de opdrachten van de vorige les (om de deelnemers in groepjes samen te vatten) werken alleen voor die ene lijst die we ls hadden genoemd. Door van het commando een functie te maken, kunnen we het op een willekeurige lijst (van die lengte) laten werken. Om een functie te definiëren gebruiken we het keyword  lambda:
> (lambda (ls) (...))
#<PROCEDURE>

Die hele lambda-uitdrukking beschrijft nu een functie die precies één argument nodig heeft. We kunnen de functie op een lijst toepassen op precies dezelfde manier als we b.v. de functie "+" op 2 en 3 konden toepassen: met een complexe uitdrukking waar de nieuwe functie de functor is en een lijst het argument:
> ( (lambda (ls) (...)) '(a b c d e f g h i) )
( (a b) (c d) (e f) (g h) i)

Om niet elke keer dat we de functie willen gebruiken die hele lambda-uitdrukking te moeten schrijven, kunnen we de lambda-uitdrukking in een variabele bewaren, d.w.z. de functie een naam geven. Indenteren helpt de overzichtelijkheid:
> (define groepjes-van-twee
        (lambda (ls)
            (...)) )

Nu kunnen we simpelweg typen:
> (groepjes-van-twee '(a b c d e f g h i) )
( (a b) (c d) (e f) (g h) i)

Een functie heeft evenveel argumenten nodig als de lijst achter het keyword lambda elementen heeft:
> (define plak-met-spatie
        (lambda (string1 string2)
             (string-append string1 " " string2)))
> (plak-met-spatie "Hallo" "Bertjan!")
"Hallo Bertjan!"
> (plak-met-spatie "Hallo")
[VM ERROR encountered!] Invalid argument count ...
 

Predikaten

Predikaten (ook wel: tests) zijn functies die #t (true) of #false teruggeven. Hun naam eindigt vaak op "?". Een simpel voorbeeld is equal?:
> (equal? "Hallo" "Hallo")
#t
> (equal? "Hallo" "Bertjan")
#f

Meer predikaten vind je op de pagina's van Walter Daelemans.

Logische operatoren

Met de keywords and, or en not kunnen complexere tests gemaakt worden:
> (define ls '(Ik denk dat we les hebben))
> (and (equal? 'Ik
                          (car ls))
            (equal? 'denk
                         (cadr ls)))
#t
> (and (equal? 'Ik
                          (car ls))
             (or (equal? 'weet
                                (cadr ls))
                   (equal? 'geloof
                                (cadr ls))))
#f

Programmacontrole (Flow of control)

Tests kunnen in conditionele uitdrukkingen gebruikt worden. Hiermee zorg je ervoor dat je programma niet altijd hetzelfde doet, maar al naar gelang de invoer passend reageert. De eenvoudigste conditionele uitdrukking gebruikt het keyword if:
> (define ls '(Ik denk dat we les hebben))
> (if (equal? 'Dag
                     (car ls))
        "Doei!"
       "Hmhm...")
"Hmhm..."
> (define ls '(Dag))
> (if (equal? 'Dag
                     (car ls))
        "Doei!"
       "Hmhm...")
"Doei!"

If heeft meestal drie argumenten:
de test (die als eerste geëvalueerd wordt),
de then-uitdrukking (die geëvalueerd wordt als de test niet #f teruggeeft) en
de else-uitdrukking (die geëvalueerd wordt als de test #f teruggeeft).

Als de else-uitdrukking ontbreekt, gebeurt er niets als de test #f teruggeeft:
> (if (equal? 'Hoi
                     (car ls))
        "Doei!")

De conditionele expressies met de keywords cond en case worden op Walter Daelemans pagina's uitgelegd.

Commentaar

De punt-komma is het commentaarteken in SCHEME. Alles wat erachter op de regel staat wordt door het programma genegeerd.

En nu alles samen

NB: Het predikaat member neemt een uitdrukking en een lijst. Het is waar als de uitdrukking een element van de lijst is.

; dit is dus commentaar
; eliza: een heel simpel soort dialoogprogramma
(define eliza
      (lambda (input)                                                                                                             ; de gebruiker moet een zin in vorm van een lijst ingeven
        (cond ((equal? '(dag) input)          "ja, doei!")                                                           ; complete zin: dag
                   ((equal? 'ik (car input))       (if (equal? 'denk (cadr input))                           ; patroon: ik denk ...
                                                                      (append  '(waarom denk je) (cddr input))
                                                                   "je hebt het altijd over jezelf!"))                       ; patroon: ik ...
                   ((member 'moeder input)    "houd je van je familie?")                                    ; trefwoord: moeder
                   ((or (equal? '(ja) input)                                                                                    ; complete zin: ja
                           (equal? '(nee) input)) "hoezo?")                                                              ; complete zin: nee
                   (else                                     (append input '(?))))))

Opdrachten

Kennelijk waren de opdrachten niet zo duidelijk geformuleerd, daarom heb ik net (9/2/2000, 15:30 uur) voorbeelden toegevoegd!!!
Sabine Buchholz

1

Schrijf een functie is-lijst die een eigen foutmelding teruggeeft als het enige argument geen lijst is (gebruik het predikaat list?).
>(is-lijst 'a)
"De input had een lijst moeten zijn!"

2

Schrijf een functie (predikaat/test) afscheid die als enige argument een lijst neemt en #t teruggeeft als de woorden in de lijst een afscheidsuitdrukking vormen (zoals: dag, doei, tot ziens, tot morgen, ...).
>(afscheid '(tot ziens))
#t
>(afscheid '(hoe gaat het ?))
#f

3

Schrijf een test x-test (waarbij x een willekeurig woord is) die waar is als x in de inputlijst voorkomt. Schrijf een bijbehorende functie x-antwoord die een passend antwoord teruggeeft. Hieronder staat een voorbeeld, maar jij moet zelf iets bedenken:
>(huiswerk-test '(Coenraad doet zijn huiswerk))
#t
>(huiswerk-test '(Coenraad zit in de bieb))
#f
>(huiswerk-antwoord)
"Succes!"

4

Schrijf een test ...-test (waarbij ... een begin van een zin is) die waar is als ... het begin van de inputlijst is.  Schrijf een bijbehorende functie ...-antwoord die een antwoord teruggeeft dat delen uit de inputzin gebruikt. Hieronder staat een voorbeeld, maar jij moet zelf iets bedenken:
>(jij-bent-een-test '(jij bent een stom programma))
#t
>(jij-bent-een-test '(hij is stom))
#f
>(jij-bent-een-antwoord '(jij bent een stom programma))
(ik ben helemaal geen stom programma)

5

Schrijf een functie die op een zin '(ik heb 2 zusters) als antwoord geeft '(maar ik heb 3 zusters !). De input en het antwoord hebben dus de vorm van een lijst! Het moet ook werken met "broers", en met alle andere getallen (gebruik het predikaat number?), en in het antwoord moet het getal altijd eentje hoger zijn dan in de input.

6

Voeg aan al je functies commentaar toe dat de werking van de functie uitlegt.
 

Speelgoed

> (set! pcs-debug-mode '())
> (load "T:/PCS/SAMPLES/DOCTOR.S")
> (doctor)

PS: Ik heb nog niet kunnen ontdekken hoe je hier goed uit komt (anders dan het hele DOS-venster te sluiten).

Oplossingen