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
- NUMBER. De getallen.
- BOOLEAN. Er zijn twee booleaanse waarden, #t en
#f, respectievelijk true en false.
- STRING. Een reeks characters.
- SYMBOL. De identifiers, gebruikt als naam van functies en
variabelen.
- VECTOR. Een datastructuur met een aantal elementen
van om het even welk datatype, toegankelijk via een index.
- CHARACTER. De alfanumerieke lettertekens en speciale
symbolen.
- LIST. Voor de compositie van complexe symbolische
expressies uit primitieve datatypes. De lege lijst () is een
lijst zonder elementen.
- PAIR. Voor de constructie van lijsten.
- PROCEDURE. Representatie van een stuk programma
(voor de manipulatie van symbolische expressies).
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.
- (STRING->LIST string): Zet een string om naar een lijst van
corresponderende characters.
- (LIST->STRING lijst): Zet een lijst
characters om naar een string.
- (VECTOR->LIST vector): zet inhoud
van vector in een lijst.
- (LIST->VECTOR lijst): Zet elementen van
een lijst in een vector.
- (NUMBER->STRING getal): Zet een getal om
naar een string.
- (STRING->NUMBER string): Zet een string met
cijfers om naar een getal.
- (CHAR->STRING character): Maak string
van een character.
- (STRING->CHAR string).
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