SCHEME SYNTAXIS EN SEMANTIEK

In dit hoofdstuk gaan we in wat meer detail in op een aantal bijkomende datatypes, een meer gedetailleerde beschrijving van de syntaxis van Scheme voor de verschillende datatypes, het `toplevel' van de Lisp Listener, en methodes voor de conversie tussen verschillende datatypes.

Datatypes

SCHEME Syntaxis

Getallen

Er zijn verschillende subtypes van het type number: integer, rational, real, complex. Er zijn verschillende schrijfwijzen voor getallen: met of zonder exponent, met of zonder teken, met verschillend grondtal.

0
+6
-3/7       ; Breuk
6.02E+23
3+4i       ; Complex getal
#b1010101  ; 85 Binair

> (+ 2/3 4/5)
1.4666666666667

Symbolen

Bij symbolen wordt geen onderscheid gemaakt tussen kleine en grote letters. Cijfers en sommige `speciale' tekens kunnen worden gebruikt in een symbool:
+ - . 0-9 (cijfers) / < = > ! ? : $ % _ $ ~ ^
Andere speciale tekens hebben een specifieke betekenis voor SCHEME en kunnen dus niet in symboolnamen worden gebruikt, zoals de spatie en de volgende tekens:
[ ] { } ( ) # | \ ` ' , " ;
Dit zijn enkele syntactisch welgevormde symbolen:

Appel  
foobar 
FoObAr 
/usr/parser/lexicon 
b^2-4*a*c
Appel_23
%person-234%
En dit enkele niet welgevormde:

ap(pel
[foo]
#person

Strings

Een string is een rijtje characters met een dubbele quote aan elke kant. Tussen twee string quotes kan om het even welk character verschijnen, inclusief de speciale tekens die niet in symboolnamen kunnen worden gebruikt. Er is 1 uitzondering, namelijk de dubbele quote (") zelf. Die kan gebruikt worden in een string door hem te laten voorafgaan door de backslash.

"Dit is (een) `string'"

"Dit is een \"string\""

Characters

{\em Character} is een datatype voor de representatie van letters, cijfers en sommige speciale tekens. De syntaxis is
#\ of
#\

#\a
#\Z
#\#
#\newline      (Newline, ga naar volgende regel)

Vectors

Een vector is een structuur waarvan de elementen verschillende datatypes kunnen hebben, en waarbij toegang tot de elementen gebeurt via een index. De syntaxis van vectors is het # teken gevolgd door een lijst met de respectievelijke elementen.
#(aap (1 2 3) "appels zijn gezond")    ; Vector met als elementen 
                                       ; een symbool, een lijst en 
                                       ; een string

Lijsten en paren

Een lijst bestaat uit een linkerhaakje, nul of meer symbolische expressies en een rechterhaakje. De lege lijst, lijst zonder elementen is (). Inbedding van lijsten kan willekeurig diep zijn, wat LISP (de familie van talen waar SCHEME toe behoord) de bijnaam Lots of Insidiously Stupid Parentheses opleverde. Eigenlijk staat LISP voor Lisp Is Simply Perfect (P. Berck, p.c.).

Moderne editors maken haakjes tellen gelukkig overbodig. Een lijst is eigenlijk een syntactische afkorting van een structuur die SCHEME-intern complexer is. Met de lijst (aap noot mies) correspondeert bijvoorbeeld de interne structuur (aap . (noot . (mies . ()))). Deze structuur bestaat uit drie paren (pairs), datastructuren met een eerste en een tweede element gescheiden door een dot. Het onderscheid tussen lijsten en paren en toepassingen van paren komen later nog aan bod.

Enkele voorbeelden van lijsten:

()                              ; Lege lijst

(#f)                            ; Lijst met element #f
(())                            ; lijst met 1 element, de lege
                                ; lijst
(foobar)

(foo 6 pi)

(* 5 (+ 1 2))

(() ())

                                ; Complexe datastructuren als
                                ; parse trees en frames kunnen
                                ; gerepresenteerd worden als
                                ; lijsten
(S (NP (DET het)(N meisje))(VP (V eet)))

(john 
  (type person)
  (age 23)
  (girlfriend (mary 
                 (type person)
                 (age 18))))

SCHEME Semantiek

De interpretatie van vectoren, characters en strings is zoals die van getallen: de expressie zelf. Verder gelden dezelfde evaluatieregels als uitgelegd in het hoofdstuk Mini-Scheme.

SCHEME Toplevel

We kunnen nu een beschrijving geven van het toplevel in een SCHEME systeem (de SCHEME interactie loop). Wanneer we interactief een symbolische expressie intikken in een SCHEME systeem gebeurt het volgende: De input wordt gelezen en syntactisch ontleed (door de primitieve functie (READ), de resulterende interne representatie van de input wordt geëvalueerd (door de functie (EVAL expressie) die de interpretatieregels van SCHEME implementeert), en het resultaat van de evaluatie wordt naar het scherm gestuurd door de functie (DISPLAY expressie) (de printer). In een imperatieve stijl ziet het toplevel er zo uit:

 loop exp := read (input);
               val := eval (exp);
               write (val, output);
      go loop
Of in SCHEME zelf:
(define (toplevel)
   (newline)                  ; ga naar volgende regel
   (display (eval (read)))      ; read-eval-write loop
   (toplevel))                ; recursieve aanroep van functie

Datatype Conversie

Er zijn in Scheme een aantal primitieve datatypeconversie procedures die het mogelijk maken sommige datatypes om te zetten naar andere. Dit is vooral nuttig bij sommige input en output operaties. Een syntactische afspraak is dat datatypeconversie procedures een naam hebben volgens het patroon input datatype -> output datatype. Enkele voorbeelden:

> (string->list "appelflap")
(#\a #\p #\p #\e #\l #\f #\l #\a #\p)

> (list->string '( #\f #\l #\a #\p))
"flap"

> (vector->list #(aap noot mies))
(aap noot mies)

> (list->vector '(1 2 3 (4 5)))
#(1 2 3 (4 5))

> (number->string 3456)
"3456"

> (number->string 3456.9)
"3.4569e3"

> (string->number "3.4569e3")
3.4569e3

> (char->integer #\newline)
10

> (integer->char 100)
#\d

Walter Daelemans <Walter.Daelemans@kub.nl>
Last modified: Tue Mar 18 13:18:11 1997