A Scheme programozási nyelv

Alprogramok, modulok

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)