I/O

Output naar scherm

Met de functie display kunnen we naar het scherm printen. Display geeft geen waarde terug, het heeft alleen een side effect. Let op: display gaat na het printen niet vanzelf naar een nieuwe regel (alleen zie dat in dit voorbeeld in PCScheme niet):
> (display "hallo")
hallo
>

Om naar een nieuwe regel te gaan is er de functie newline. Ook deze functie heeft alleen een side effect.
> (newline)

>

Begin

Vaak willen we natuurlijk iets laten printen en daarna naar een nieuwe regel. Dan vatten we twee (of meer) uitdrukkingen samen met het keyword begin. Begin evalueert zijn argumenten van links naar rechts, en geeft terug wat het laatste argument teruggeeft. Omdat in ons voorbeeld newline niets teruggeeft, geeft de hele begin-uitdrukking ook niets terug. Je ziet dus alleen de side effects:
> (define naam "Bertjan")
> (begin (display "hallo ")
               (display naam)
               (newline))
hallo Bertjan
>

In het volgende voorbeeld zie je wel dat alleen de waarde van de laatste uitdrukking teruggegeven wordt. (Daarom zal je zoiets in de praktijk ook niet gebruiken).
> (begin (+ 1 2)
               (+ 2 3)
               (+ 3 4))
7

Input van scherm

De functie read leest één object (string, symbool, ...) van het scherm, en geeft dit terug, waarna je het b.v. met define in een variabele kunt opslaan. In het voorbeeld is de tweede regel dus door de gebruiker getypt:
> (define input (read))
"dit is een test"
> input
"dit is een test"

Als je meer dan één object (hier: 3 symbolen) intoetst, krijg je een foutmelding:
> (define input (read))
dit is verkeerd
[VM ERROR encountered!] Variable not defined in current environment
IS
[VM ERROR encountered!] Variable not defined in current environment
VERKEERD
> input
dit

De basis voor een interactief programma

(define voorbeeld
  (lambda ()
     (begin                                             ; begin na lambda is niet noodzakelijk
        (startzin)                                    ; schrijft iets naar het scherm zodat de gebruikers weten wat zij moeten doen
        (voorbeeld-r))))                        ; begin van de recursie

(define voorbeeld-r                            ; het eigenlijke programma
   (lambda ()
       (begin                                            ; begin na lambda is niet noodzakelijk
          (define input (read))                 ; leest van het scherm
          (if (einde? input)                       ; test of de gebruiker het programma wil beëindigen
               (afsluitzin)                            ; schrijft een of ander afscheidsgroet
            (begin                                       ; dit begin is wel noodzakelijk, omdat ...
                (produce_output input)       ; ... produce_output en de recursieve oproep voorbeeld-r ...
                (voorbeeld-r))))))              ; ... samen de else-uitdrukking vormen

(define startzin
    (lambda ()                                         ; hier hebben we de begin weggelaten
        (display "Hoi")
        (newline)))

(define einde?
     (lambda (zin)                                   ; hier hebben we de begin weggelaten
          (equal? 'stop zin)))                    ; dit is maar een simpel voorbeeld

(define afsluitzin
    (lambda ()                                         ; hier hebben we de begin weggelaten
        (display "Dag")
        (newline)))

(define produce_output
     (lambda (zin)                                   ; hier hebben we de begin weggelaten
        (display "Ga door")                     ; dit is een wel erg simpel voorbeeld: het programma antwoort altijd hetzelfde
        (newline)))

Input en output met files

Voordat je naar een file kan schrijven of eruit lezen moet je een port ernaartoe openen. De functies open-input-file en open-output-file nemen elk een filenaam (als string) en geven een port terug die je in een variabele kan opslaan:
> (define mijn-input-poort (open-input-file "college.txt"))
> (define mijn-output-poort (open-output-file "test.txt"))

Om van of naar een port te lezen of te schrijven gebruik je gewoon display, newline en read, maar geef je ze als extra argument de port mee:
> (define woord (read mijn-poort))
> woord
...
> (display woord mijn-output-poort)
> (newline mijn-output-poort)

Als je een port niet meer wil gebruiken moet je hem dicht doen:
> (close-input-port mijn-input-poort)
> (close-output-port mijn-output-poort)

Het toevalswoordprogramma

(define toevalswoord
   (lambda (file)
      (define poort (open-input-file file) )
      (define woordenlijst (lees_woorden '() poort ) )
      (close poort)
      (list-ref woordenlijst (random (length woordenlijst) ) ) ) )

(define lees_woorden
   (lambda (lijst poort)
      (define woord (read poort))
      (if (equal? eof woord)
         lijst
         (lees_woorden (cons woord lijst) poort) ) ) )

Opdrachten

1

Schrijf een interactieve versie van galgje of lingo (met de functies uit de vorige opdrachten).

2

Wat hebben we nog nodig om boter, kaas en eieren te kunnen schrijven?

3

Schrijf een interactieve versie van eliza (met de functies uit les 3).

4

Schrijf een eliza die stiekem het hele "gesprek" in een file meeschrijft.

5

Wat wil je als tussenopdracht doen? (voor wie niks weet)

Oplossingen