A definíciós kifejezések
segítségével nevek és értékek
köthetők őssze:
(define nev kif)
Például:
(define pi 3.14)
Ez a pi-t 3.14-nek definiálja. Ez nem
értékadás, hiszen nem köthető
később új érték a névhez.
Függvények
Lambda kifejezések
A felhasználók által definiált
függvények lambda kifejezések
segítségével adhatók meg. A lambda
kifejezések névtelen függvények. Ezek a
következő formában írandók:
(lambda (id...) kif )
A (id...) helyére a formális paraméterek
listája kerül, a kif a lambda kifejezés törzse.
Két példa lambda kifejezésre:
((lambda (x) (* x x)) 3) ---> 9
((lambda (x y) (+ x y)) 3 4) ---> 7
Ez a függvény pedig egy szám négyzetét
számítja ki:
(define square (lambda (x) (* x x)))
Példa az alkalmazására:
(square 3) ---> értéke: 9
Néhány további
függvénydefiníció (a faktoriális, a
legnagyobb közös osztót kiszámító, a
Fibonacci- és az Ackerman-függvény):
(define fac
(lambda (n)
(if (= n 0)
1
(* n (fac (- n 1))))))
(define fib
(lambda (n)
(if (= n 0)
0
(if (= n 1)
1
(+ (fib (- n 1)) (fib (- n 2)))))))
(define ack
(lambda (m n)
(if (= m 0)
(+ n 1)
(if (= n 0)
(ack (- m 1) 1)
(ack (- m 1) (ack m (- n 1)))))))
(define gcd
(lambda (a b)
(if (= a b)
a
(if (> a b)
(gcd (- a b) b)
(gcd a (- b a))))))
Listakezelő függvények definíciói:
(define sum
(lambda (l)
(if (null? l)
0
(+ (car l) (sum (cdr l))))))
(define product
(lambda (l)
(if (null? l)
1
(* (car l) (sum (cdr l))))))
(define length
(lambda (l)
(if (null? l)
0
(+ 1 (length (cdr l))))))
(define reverse
(lambda (l)
(if (null? l)
nil
(append (reverse (cdr l)) (list (car l))))))
Egymásba ágyazott definíciók
A Scheme-ben lokális definíciókat a
definíciók egymásba ágyazásával
adhatunk meg. A lokális definíciók
megadásához a let, let* és
letrec függvények használhatók. A
define függvény definícióját
kiterjesztették úgy, hogy lokális
definíciókat is lehessen benne használni. A szintaxis
a következő:
Scheme szintaxis
E -> Kifejezés
I -> Azonosító (változó)
...
B -> Kötés (szimbólumot értékhez)
...
E ::= ...| (lambda (I...) E... ) |
(let B_0 E_0) | (let* B1 E1) | (letrec B2
E2) |...
B ::= ((I E)...)
Vegyük észre, hogy definíciók sorozata is
megadható. A hatékonyság növelése
érekében mindhárom "let" függvényt
másképp interpretálják. A
különböző let értékek
számítása és kötése
párhuzamosan történik, így a
definíciók egymástól függetlenek. A
let* értékek számítása
és kötése szekvenciálisan történik,
így a későbbi definíciók függhetnek
a korábbiaktól. A letrec kötések
már az értékek számítasakor
érvényben vannak, így lehetővé
válik kölcsönösen rekurzív definíciók
megadása. Egy példa a lokális definíciók
használatára a beszúrásos rendező
függvény. Az isort törzse két kifejezést tartalmaz,
az első egy letrec kifejezés, a második az a
kifejezés, aminek az értékét vissza kell adni.
(define isort (lambda (l)
(letrec
((insert (lambda (x l)
(if (null? l)
(list x)
(if (<= x (car l))
(cons x l)
(cons (car l) (insert x (cdr l))))))))
(if (null? l)
nil
(insert (car l) (isort (cdr l)))))))
mivel az insert definíciója rekurzív,
letrec-et használ. Néhány
további példa:
; ez az x-hez az 5 értéket köti és 10-et ad vissza.
(let ((x 5)) (* x 2))
; ez az x-hez a 10-et, a z-hez az 5-öt köti és 50-et ad vissza.
(let ((x 10) (z 5)) (* x z))
A let-ek egymásba ágyazhatók. Például a következő kifejezés
(let ((a 3) (b 4)
(let ((double (* 2 a))
(triple (* 3 b)))
(+ double triple))))
; értéke 18.
Magasabbrendű függvények
A magasabbrendű függvény (más néven
funkcionál) olyan függvény, ami vagy függvényt
vár paraméterként, vagy a visszatérési
értéke függvény. A Scheme-ben ilyen függvények
léteznek, bár beépített magasabbrendű
függvény nincs sok. Az apply és a map ilyenek.
Az apply függvény alkalmazza az első argumentumát
a másodikra.
(apply + '(7 5))
;értéke: 12
(apply max '(3 7 2 9))
;értéke: 9
A map függvény egy listát ad vissza, amit
úgy állít elő, hogy az első
argumentumát alkalmazza a második argumentumának
minden elemére.
(map odd? '(2 3 4 5 6))
;értéke: (() #t () #t ())
és egy példa egy paraméterként kapott
"curried" függvényre. (A dbl
megduplazza az argumentuma értékét.)
(define dbl (lambda (x) (* 2 x)))
;értéke: dbl
(map dbl '(1 2 3 4))
;értéke: (2 4 6 8)
Az elözö példa így is írható:
(map (* 2) '(1 2 3 4))
;értéke: (2 4 6 8)