You are on page 1of 33

IDZ DO

PRZYKADOWY ROZDZIA
SPIS TRECI

KATALOG KSIEK
KATALOG ONLINE
ZAMW DRUKOWANY KATALOG

TWJ KOSZYK
DODAJ DO KOSZYKA

CENNIK I INFORMACJE
ZAMW INFORMACJE
O NOWOCIACH
ZAMW CENNIK

CZYTELNIA
FRAGMENTY KSIEK ONLINE

Projektowanie
oprogramowania.
Wstp do programowania
i techniki komputerowej
Autorzy: Matthias Felleisen, Robert Bruce Findler,
Matthew Flatt, Shriram Krishnamurthi
Tumaczenie: Bartosz Grabski, Mikoaj Szczepaniak
ISBN: 83-7197-922-3
Tytu oryginau: How to Design Programs
Format: B5, stron: 644
Przykady na ftp: 32 kB
Umiejtno programowania nie ma ju charakteru czysto zawodowego. Ksigowi
musz si posugiwa arkuszami kalkulacyjnymi i edytorami tekstu, fotografowie
korzystaj z edytorw zdj, muzycy programuj syntezatory, za profesjonalni
programici tworz skomplikowane aplikacje. Programowanie jest wic bardzo
podan umiejtnoci, potrzebn nie tylko informatykom. Projektowanie
oprogramowania wymaga takich samych zdolnoci analitycznych, jak matematyka.
Jednak, w przeciwiestwie do matematyki, praca z programami jest aktywnym
sposobem zdobywania wiedzy. Obcowanie z oprogramowaniem daje moliwo staej
interakcji, co pozwala na zgbianie wiedzy, eksperymentowanie z ni oraz na sta
samoocen.
Autorzy tej klasycznej publikacji stawiaj tez, i kady powinien nauczy si, jak
projektowa oprogramowanie i wanie nauka podstaw projektowania jest jej tematem
gwnym. W ksice znajdziesz wiele podstawowych algorytmw, wyjanienia takich
poj, jak akumulacja wiedzy czy rwno ekstensjonalna i intensjonalna, sowem
wszystko to, co stanowi teoretyczn podstaw wiedzy programistycznej.
Poznasz midzy innymi:
Podstawowe struktury, z ktrych skadaj si programy komputerowe
Proste i zoony typy danych
Metody przetwarzania danych
Programowanie z uyciem rekurencji, algorytmy z nawracaniem
Projektowanie abstrakcyjne
Sposoby gromadzenia wiedzy
Wykorzystanie wektorw

Wydawnictwo Helion
ul. Chopina 6
44-100 Gliwice
tel. (32)230-98-63
e-mail: helion@helion.pl

Z lektury ksiki Projektowanie oprogramowania. Wstp do programowania i techniki


komputerowej skorzystaj zarwno studenci informatyki, jak te i suchacze innych
kierunkw oraz wszystkie osoby, ktre chc podbudowa swoj wiedz praktyczn
solidnymi i przydatnymi podstawami teoretycznymi.

Spis treci

Przedmowa ............................................................................................................9
Dlaczego kady powinien uczy si programowa? .................................................................... 11
Metody projektowania ....................................................................................................................... 12
Wybr Scheme i DrScheme ............................................................................................................... 14
Podzia ksiki..................................................................................................................................... 15
Podzikowania .................................................................................................................................... 18

Cz I Przetwarzanie prostych typw danych

19

1.

Studenci, nauczyciele i komputery..........................................................21

2.

Liczby, wyraenia i proste programy .....................................................23


Liczby i arytmetyka ............................................................................................................................ 23
Zmienne i programy .......................................................................................................................... 26
Problemy ze zrozumieniem treci zada ........................................................................................ 29
Bdy...................................................................................................................................................... 30
Projektowanie programw................................................................................................................ 33

3.

Program skada si z funkcji i definicji zmiennych ..............................39


Skadanie funkcji................................................................................................................................. 40
Definicje zmiennych ........................................................................................................................... 43
Proste wiczenia w tworzeniu funkcji............................................................................................. 44

4.

Instrukcje warunkowe i funkcje...............................................................47


Wartoci logiczne i relacje ................................................................................................................. 47
Funkcje testujce warunki ................................................................................................................. 50
Warunki i funkcje warunkowe ......................................................................................................... 54
Projektowanie funkcji warunkowych.............................................................................................. 57

5.

Informacje symboliczne.............................................................................63
Proste wiczenia z symbolami.......................................................................................................... 65

6.

Dane zoone. Cz 1.: Struktury ...........................................................69


Struktury .............................................................................................................................................. 69
wiczenie rozszerzone: rysowanie prostych obrazw .................................................................... 72

SPIS TRECI

Definicje struktur ................................................................................................................................ 75


Definicje danych.................................................................................................................................. 79
Projektowanie funkcji przetwarzajcych dane zoone .................................................................... 82
Rozszerzone wiczenie: przemieszczanie okrgw i prostoktw ............................................ 87
Rozszerzone wiczenie: gra w szubienic ...................................................................................... 91

7.

Rodzaje danych...........................................................................................95
Mieszanie i rozrnianie danych ..................................................................................................... 95
Projektowanie funkcji przetwarzajcych dane mieszane ........................................................... 100
Skadanie funkcji powtrka ....................................................................................................... 104
Rozszerzone wiczenie: przesuwanie figur.................................................................................. 107
Bdne dane wejciowe .................................................................................................................... 108

W1. Skadnia i semantyka ...............................................................................111


Sownictwo jzyka Scheme ............................................................................................................. 112
Gramatyka jzyka Scheme .............................................................................................................. 112
Znaczenie w jzyku Scheme ........................................................................................................... 114
Bdy ........................................................ ...........................................................................................118
Wyraenia logiczne .......................................................................................................................... 121
Definicje zmiennych ......................................................................................................................... 122
Definicje struktur .............................................................................................................................. 124

Cz II Przetwarzanie danych dowolnej wielkoci 127


9.

Dane zoone. Cz 2.: Listy .................................................................129


Listy .....................................................................................................................................................129
Definicje danych dla list o dowolnej dugoci ............................................................................. 133
Przetwarzanie list o dowolnej dugoci ........................................................................................ 135
Projektowanie funkcji dla rekursywnych definicji danych........................................................ 139
Wicej na temat przetwarzania prostych list ............................................................................... 142

10. Wicej na temat przetwarzania list........................................................147


Funkcje zwracajce listy................................................................................................................... 147
Listy zawierajce struktury ............................................................................................................. 152
Rozszerzone wiczenie: przemieszczanie obrazw .................................................................... 158

11. Liczby naturalne .......................................................................................161


Definiowanie liczb naturalnych...................................................................................................... 161
Przetwarzanie liczb naturalnych dowolnej wielkoci................................................................. 163
Rozszerzone wiczenie: tworzenie list, testowanie funkcji........................................................ 166
Alternatywne definicje danych dla liczb naturalnych .................................................................. 168
Wicej o naturze liczb naturalnych................................................................................................ 173

12. czenie funkcji. Powtrka.....................................................................177


Projektowanie skomplikowanych programw ............................................................................ 177
Rekursywne funkcje zewntrzne ................................................................................................... 178
Uoglnianie problemw i funkcji................................................................................................... 183
Rozszerzone wiczenie: przestawianie sw ................................................................................ 187

W2. Skracanie list .............................................................................................191

SPIS TRECI

Cz III Wicej o przetwarzaniu danych


dowolnej wielkoci

197

14. Wicej rekurencyjnych definicji danych ...............................................199


Struktury w strukturach .................................................................................................................. 199
Rozszerzone wiczenie: drzewa poszukiwa binarnych ........................................................... 208
Listy w listach.................................................................................................................................... 212
Rozszerzone wiczenie: obliczanie wyrae jzyka Scheme..................................................... 215

15. Wzajemne odwoania w definicjach danych........................................217


Listy struktur. Listy w strukturach................................................................................................ 217
Projektowanie funkcji dla definicji danych zawierajcych wzajemne odwoania ................. 223
Rozszerzone wiczenie: wicej na stronach WWW..................................................................... 225

16. Tworzenie programw metod iteracyjnego ulepszania...................227


Analiza danych.................................................................................................................................. 228
Definiowanie i ulepszanie klas danych......................................................................................... 229
Ulepszanie funkcji i programw .................................................................................................... 232

17. Przetwarzanie dwch skomplikowanych elementw danych .........235


Jednoczesne przetwarzanie dwch list. Przypadek 1. ................................................................. 235
Jednoczesne przetwarzanie dwch list. Przypadek 2. ................................................................. 237
Jednoczesne przetwarzanie dwch list. Przypadek 3. ................................................................. 240
Upraszczanie funkcji ........................................................................................................................ 245
Projektowanie funkcji pobierajcych dwie zoone dane wejciowe ....................................... 247
wiczenia z przetwarzania dwch zoonych danych wejciowych....................................... 248
Rozszerzone wiczenie: obliczanie wyrae jzyka Scheme. Cz 2. .................................... 251
Rwno i testowanie....................................................................................................................... 253

W3. Lokalne definicje i zasig leksykalny ....................................................261


Organizowanie programw za pomoc sowa local................................................................... 261
Zasig leksykalny i struktura blokowa ......................................................................................... 276

Cz IV Projektowanie abstrakcyjne

281

19. Podobiestwa w definicjach ...................................................................283


Podobiestwa w funkcjach.............................................................................................................. 283
Podobiestwa w definicjach danych ............................................................................................. 292

20. Funkcje s wartociami............................................................................297


Skadnia i semantyka ....................................................................................................................... 297
Kontrakty dla abstrakcyjnych i polimorficznych funkcji ........................................................... 299

21. Projektowanie funkcji abstrakcyjnych na podstawie przykadw...303


Abstrahowanie na podstawie przykadw................................................................................... 303
wiczenia z abstrakcyjnymi funkcjami przetwarzajcymi listy ............................................... 309
Abstrakcja i pojedynczy punkt kontroli........................................................................................ 311
Rozszerzone wiczenie: przemieszczanie obrazw jeszcze raz ................................................ 312
Uwaga: Projektowanie abstrakcji na podstawie szablonw ...................................................... 314

SPIS TRECI

22. Projektowanie abstrakcji .........................................................................317


Funkcje zwracajce funkcje ............................................................................................................. 317
Projektowanie abstrakcji z funkcjami jako wartociami............................................................. 319
Pierwsze spojrzenie na graficzny interfejs uytkownika ........................................................... 322

23. Przykady matematyczne........................................................................331


Cigi i szeregi .................................................................................................................................... 331
Cigi i szeregi arytmetyczne ........................................................................................................... 333
Cigi i szeregi geometryczne .......................................................................................................... 334
Pole powierzchni pod wykresem funkcji...................................................................................... 338
Nachylenie funkcji ............................................................................................................................ 340

W4. Bezporednie definiowanie funkcji .......................................................345

Cz V Rekursja generatywna

351

25. Nowa posta rekursji ...............................................................................353


Modelowanie kuli na stole .............................................................................................................. 354
Szybkie sortowanie........................................................................................................................... 357

26. Projektowanie algorytmw.....................................................................363


Zakoczenie ....................................................................................................................................... 365
Rekursja strukturalna a generatywna............................................................................................ 368
Dokonywanie wyborw .................................................................................................................. 369

27. Rne algorytmy rekurencyjne ..............................................................375


Fraktale ............................................................................................................................................... 375
Od plikw do linii, od list do list list............................................................................................. 380
Wyszukiwanie binarne .................................................................................................................... 384
Metoda Newtona .............................................................................................................................. 390
Rozszerzone wiczenie: eliminacja Gaussa .................................................................................. 392

28. Algorytmy z nawracaniem .....................................................................397


Przechodzenie grafw...................................................................................................................... 397
Rozszerzone wiczenie: szachowanie hetmanw........................................................................ 403

W5. Koszt obliczeniowy oraz wektory .........................................................405


Czas konkretny, czas abstrakcyjny ................................................................................................ 405
Definicja wyraenia rzdu........................................................................................................... 410
Pierwsze spojrzenie na wektory..................................................................................................... 412

Cz VI Gromadzenie wiedzy

423

30. Utrata wiedzy ...........................................................................................425


Problem przetwarzania strukturalnego ........................................................................................ 425
Problem rekursji generatywnej....................................................................................................... 429

31. Projektowanie funkcji z akumulatorem................................................433


Czy akumulator jest potrzebny? .................................................................................................... 433
Funkcje z akumulatorem ................................................................................................................. 434
Przeksztacanie funkcji na funkcje z akumulatorem................................................................... 436

SPIS TRECI

32. Dalsze uycie akumulacji........................................................................447


Rozszerzone wiczenie: akumulatory i drzewa........................................................................... 447
Rozszerzone wiczenie: misjonarze i ludoercy .......................................................................... 452
Rozszerzone wiczenie: plansza gry Solitaire .............................................................................. 455

W6. Natura liczb niedokadnych ...................................................................457


Arytmetyka liczb o staym rozmiarze ........................................................................................... 457
Przepenienie ..................................................................................................................................... 463
Niedomiar .......................................................................................................................................... 464
Liczby w DrScheme.......................................................................................................................... 465

Cz VII Zmiana stanu zmiennych

467

34. Pami dla funkcji ....................................................................................469


35. Przypisanie do zmiennych......................................................................475
Dziaanie prostych przypisa ......................................................................................................... 475
Sekwencja wyrae obliczeniowych.............................................................................................. 477
Przypisania i funkcje ........................................................................................................................ 479
Pierwszy uyteczny przykad......................................................................................................... 482

36. Projektowanie funkcji z pamici ..........................................................485


Zapotrzebowanie na pami ........................................................................................................... 485
Pami i zmienne stanu ................................................................................................................... 487
Funkcje inicjalizujce pami .......................................................................................................... 489
Funkcje zmieniajce pami ............................................................................................................ 489

37. Przykady zastosowania pamici...........................................................497


Inicjalizacja stanu .............................................................................................................................. 497
Zmiana stanu przez interakcj z uytkownikiem ....................................................................... 500
Zmiany stanu przez rekursj .......................................................................................................... 508
wiczenia na zmianach stanu ........................................................................................................ 514
Rozszerzone wiczenie: zwiedzanie .............................................................................................. 516

W7. Kocowa skadnia i semantyka..............................................................519


Sownik Advanced Scheme ............................................................................................................. 519
Gramatyka Advanced Scheme ....................................................................................................... 519
Znaczenie Advanced Scheme ......................................................................................................... 522
Bdy w Advanced Scheme............................................................................................................. 534

Cz VIII Zmiana wartoci zoonych

539

39. Hermetyzacja ............................................................................................541


Abstrahowanie ze zmiennymi stanu ............................................................................................. 541
wiczenia z hermetyzacji ................................................................................................................ 551

40. Mutacja struktur .......................................................................................553


Struktury z funkcji ............................................................................................................................ 553
Mutacja struktur funkcjonalnych ................................................................................................... 556

SPIS TRECI

Mutacja struktur................................................................................................................................ 558


Mutacja wektorw ............................................................................................................................ 565
Zmiana zmiennych, zmiana struktur ............................................................................................ 567

41. Projektowanie funkcji zmieniajcych struktury ..................................571


Po co mutowa struktury ................................................................................................................ 571
Zasady projektowania strukturalnego i mutacji, cz 1. .......................................................... 572
Zasady projektowania strukturalnego i mutacji, cz 2. .......................................................... 583
wiczenie rozszerzone: ruchome obrazy po raz ostatni............................................................ 594

42. Rwno.....................................................................................................595
Rwno ekstensjonalna .................................................................................................................. 595
Rwno intensjonalna..................................................................................................................... 596

43. Zmiana struktur, wektorw i obiektw................................................601


wiczenia praktyczne z wektorami............................................................................................... 601
Zbiory struktur z cyklami................................................................................................................ 616
Nawracanie ze stanem ..................................................................................................................... 626

Zakoczenie ..............................................................................................629
Technika obliczeniowa..................................................................................................................... 629
Programowanie ................................................................................................................................. 630
Krok naprzd..................................................................................................................................... 631

Dodatki

633

Skorowidz..................................................................................................635

17

Przetwarzanie dwch
skomplikowanych elementw danych

Czasami funkcja pobiera dwa argumenty nalece do klas zdefiniowanych za pomoc


skomplikowanych definicji danych. W niektrych przypadkach jeden z argumentw
powinien by traktowany tak, jakby by argumentem atomowym; precyzyjnie sformuowany opis celu zazwyczaj to wyjania. W innych przypadkach oba argumenty musz
by przetwarzane rwnolegle. Czasem funkcja bdzie musiaa bra pod uwag wszystkie
moliwe przypadki i odpowiednio przetwarza dane argumenty. Ten rozdzia ilustruje
te trzy moliwoci za pomoc przykadw i wprowadza rozszerzon metod projektowania dla ostatniego przypadku. W ostatnim podrozdziale omawiamy rwnowano
danych zoonych i jej zwizek z procesem testowania; ma to istotne znaczenie dla automatyzacji testw funkcji.

Jednoczesne przetwarzanie dwch list. Przypadek 1.


Przeanalizuj nastpujcy kontrakt, opis celu i nagwek:
;; zastap-empty-lista : lista-liczb lista-liczb -> lista-liczb
;; tworzy now list zastpujc empty w licie dana-lista-liczb1 list dana-lista-liczb2
(define (zastap-empty-lista dana-lista-liczb1 dana-lista-liczb2) )
Kontrakt mwi, e funkcja pobiera dwie listy; z takim zdarzeniem nie spotkalimy si
wczeniej. Zobaczmy, jak nasza metoda projektowania sprawdzi si w tym przypadku.
Po pierwsze, tworzymy przykady. Przypumy, e pierwsz dan wejciow jest
empty. Funkcja zastap-empty-lista powinna w takim przypadku zwrci drugi argument,
niezalenie od tego, co zawiera:
(zastap-empty-lista empty L)
=L
W powyszym rwnaniu L reprezentuje dowoln list liczb. Przypumy teraz, e
pierwszy argument jest rny od empty. Opis celu mwi, e powinnimy w takim przypadku zastpi empty na kocu listy dana-lista-liczb1 list dana-lista-liczb2:

236

17. PRZETWARZANIE DWCH SKOMPLIKOWANYCH ELEMENTW DANYCH

(zastap-empty-lista (cons 1 empty) L)


;; oczekiwana warto:
(cons 1 L)
(zastap-empty-lista (cons 2 (cons 1 empty)) L)
;; oczekiwana warto:
(cons 2 (cons 1 L))
(zastap-empty-lista (cons 2 (cons 11 (cons 1 empty))) L)
;; oczekiwana warto:
(cons 2 (cons 11 (cons 1 L)))
W powyszych przykadach L ponownie reprezentuje dowoln list liczb.
Przykady sugeruj, e tak dugo, jak drugi argument jest list, nie ma znaczenia, co
on zawiera; w przeciwnym przypadku nie miaoby sensu zastpowanie empty drugim
argumentem. Oznacza to, e majc na uwadze pierwszy argument, powinnimy wykorzysta szablon dla funkcji przetwarzajcych listy:
(define (zastap-empty-lista dana-lista-liczb1 dana-lista-liczb2)
(cond
((empty? dana-lista-liczb1) )
(else (first dana-lista-liczb1) (zastap-empty-lista (rest dana-lista-liczb1)
dana-lista-liczb2) )))
Drugi argument traktujemy na razie tak, jakby by dan atomow.
Wypenijmy teraz puste miejsca w szablonie zgodnie z zaleceniami metody projektowania. Jeli lista dana-lista-liczb1 jest pusta, funkcja zastap-empty-lista zwraca dana-lista-liczb2
zgodnie z naszymi przykadami. W drugiej klauzuli wyraenia cond, odpowiadajcej danej
na wejciu niepustej licie dana-lista-liczb1, musimy przeanalizowa dostpne wyraenia:
(1) (first dana-lista-liczb1) wyciga pierwszy element listy,
(2) (zastap-empty-lista (rest dana-lista-liczb1) dana-lista-liczb2) zamienia empty na licie
(rest dana-lista-liczb1) list dana-lista-liczb2.
Aby lepiej zrozumie, co to oznacza, przeanalizuj poniszy przykad:
(zastap-empty-lista (cons 2 (cons 11 (cons 1 empty))) L)
;; oczekiwana warto:
(cons 2 (cons 11 (cons 1 L)))
Powyej (first dana-lista-liczb1) wynosi 2, (rest dana-lista-liczb1) ma warto (cons 11 (cons
1 empty)), za (zastap-empty-lista (rest dana-lista-liczb1) dana-lista-liczb2) zwraca warto
(cons 11 (cons 1 dana-lista-liczb2)). czc liczb 2 z ostatni wartoci za pomoc instrukcji cons, moemy otrzyma podany wynik. Oglnie:
(cons (first dana-lista-liczb1) (zastap-empty-lista (rest dana-lista-liczb1) dana-listaliczb2))
jest wynikiem drugiej klauzuli wyraenia cond. Listing 17.1 zawiera kompletn definicj
funkcji.

JEDNOCZESNE PRZETWARZANIE DWCH LIST. PRZYPADEK 2.

237

Listing 17.1. Kompletna definicja funkcji zastap-empty-lista


;; zastap-empty-lista : lista-liczb lista-liczb -> lista-liczb
;; tworzy now list zastpujc empty w licie dana-lista-liczb1 list dana-lista-liczb2
(define (zastap-empty-lista dana-lista-liczb1 dana-lista-liczb2)
(cond
((empty? dana-lista-liczb1) dana-lista-liczb2)
(else (cons (first dana-lista-liczb1) (zastap-empty-lista (rest dana-lista-liczb1)
dana-lista-liczb2)))))

wiczenia
wiczenie 17.1. W wielu wiczeniach uywalimy operacji append jzyka Scheme, ktra
pobiera trzy listy i zestawia ich elementy w jedn list:
(append (list 'a) (list 'b 'c) (list 'd 'e 'f))
;; oczekiwana warto:
(list 'a 'b 'c 'd 'e 'f)
Wykorzystaj funkcj zastap-empty-lista do zdefiniowania funkcji nasz-append, ktra
powinna dziaa identycznie jak append udostpniany w jzyku Scheme.
wiczenie 17.2. Opracuj funkcj krzyzuj, ktra pobierze list symboli oraz list liczb
i zwrci wszystkie moliwe pary symboli z liczbami.
Przykad:
(krzyzuj '(a b c) '(1 2))
;; oczekiwana warto:
(list (list 'a 1) (list 'a 2) (list 'b 1) (list 'b 2) (list 'c 1) (list 'c 2))

Jednoczesne przetwarzanie dwch list. Przypadek 2.


W rozdziale 10. opracowalimy funkcj godziny->wynagrodzenie obliczajc wynagrodzenie pracownikw na podstawie przepracowanych godzin. Funkcja pobieraa list
liczb (przepracowanych przez pracownikw godzin) i zwracaa inn list liczb (nalenych wynagrodze). Dla uproszczenia zaoylimy, e wszyscy pracownicy maj tak
sam stawk godzinow. Nawet jednak mae firmy zatrudniaj pracownikw na zrnicowanych warunkach. Przewanie ksigowy firmy utrzymuje dwa zbiory informacji:
sta, ktra midzy innymi zawiera stawk godzinow danego pracownika, oraz tymczasow, w ktrej zawarta jest informacja o liczbie przepracowanych w ostatnich miesicach godzin.
Nowy, rozszerzony opis problemu oznacza, e funkcja powinna pobiera dwie listy.
Aby uproci sobie ten problem, zamy, e listy zawieraj jedynie liczby: jedna
stawki godzinowe, druga liczby przepracowanych godzin. Oto nasz kontrakt, opis
celu i nagwek:

238

17. PRZETWARZANIE DWCH SKOMPLIKOWANYCH ELEMENTW DANYCH

;; godziny->wynagrodzenia : lista-liczb lista-liczb -> lista-liczb


;; konstruuje now list zawierajc iloczyny odpowiednich
;; elementw list dana-lista-liczb1 i dana-lista-liczb2
;; ZAOENIE: listy maj rwn dugo
(define (godziny->wynagrodzenia dana-lista-liczb1 dana-lista-liczb2) )
Moemy traktowa list dana-lista-liczb1 jako list stawek godzinowych, za dana-listaliczb2 jako list przepracowanych w ostatnim miesicu godzin. Aby otrzyma list wynagrodze, musimy przemnoy odpowiednie liczby z obu list.
Spjrzmy na kilka przykadw:
(godziny->wynagrodzenia empty empty)
;; oczekiwana warto:
empty
(godziny->wynagrodzenia (cons 5.65 empty) (cons 40 empty))
;; oczekiwana warto:
(cons 226.0 empty)
(godziny->wynagrodzenia (cons 5.65 (cons 8.75 empty))
(cons 40.0 (cons 30.0 empty)))
;; oczekiwana warto:
(cons 226.0 (cons 262.5 empty))
We wszystkich trzech przykadach na wejciu funkcji podano pary list takich samych
dugoci. Jak napisalimy w dodatku do opisu celu, funkcja zakada, e dane speniaj ten
warunek i faktycznie, stosowanie funkcji z naruszeniem tego warunku nie ma sensu.
Warunek dotyczcy danych wejciowych mona wyjani podczas opracowywania
szablonu. Konkretnie, warunek mwi, e (empty? dana-lista-liczb1) ma warto true wtedy
i tylko wtedy, gdy (empty? dana-lista-liczb2) ma warto true. Co wicej, (cons? dana-listaliczb1) ma warto true wtedy i tylko wtedy, gdy (cons? dana-lista-liczb2) ma warto true.
Innymi sowy, warunek upraszcza projekt struktury wyrae warunkowych cond w szablonie, poniewa oznacza, e szablon jest podobny do szablonu dla funkcji przetwarzajcych listy:
(define (godziny->wynagrodzenia dana-lista-liczb1 dana-lista-liczb2)
(cond
((empty? dana-lista-liczb1) )
(else )))
W pierwszej klauzuli cond zarwno dana-lista-liczb1 jak i dana-lista-liczb2 s listami
pustymi empty. Nie potrzebujemy wic adnego selektora. W drugiej klauzuli zarwno dana-lista-liczb1 jak i dana-lista-liczb2 s skonstruowanymi listami, co oznacza, e
potrzebujemy czterech selektorw:
(define (godziny->wynagrodzenia dana-lista-liczb1 dana-lista-liczb2)
(cond
((empty? dana-lista-liczb1) )

JEDNOCZESNE PRZETWARZANIE DWCH LIST. PRZYPADEK 2.

239

(else
(first dana-lista-liczb1) (first dana-lista-liczb2)
(rest dana-lista-liczb1) (rest dana-lista-liczb2) )))
Poniewa ostatnie dwa selektory dotycz list o identycznych dugociach, w oczywisty
sposb moemy je wykorzysta w naturalnej rekursji funkcji godziny->wynagrodzenia:
(define (godziny->wynagrodzenia dana-lista-liczb1 dana-lista-liczb2)
(cond
((empty? dana-lista-liczb1) )
(else
(first dana-lista-liczb1) (first dana-lista-liczb2)
(godziny->wynagrodzenia (rest dana-lista-liczb1) (rest dana-lista-liczb2)) )))
Jedynym niezwykym elementem tego szablonu jest rekursywne wywoanie funkcji zoone z dwch wyrae, z ktrych oba s selektorami dwch argumentw funkcji. Jak si
ju przekonalimy, idea dziaania funkcji jest atwa do wytumaczenia dziki zaoeniu,
e dana-lista-liczb1 i dana-lista-liczb2 maj rwn dugo.
Podczas definiowania funkcji bdziemy postpowa zgodnie z zaleceniami metody
projektowania. Pierwszy przykad oznacza, e odpowiedzi pierwszej klauzuli wyraenia cond powinna by lista pusta empty. W drugiej klauzuli mamy do dyspozycji trzy
wartoci:
(1) (first dana-lista-liczb1), ktra reprezentuje pierwszy element listy stawek godzinowych;
(2) (first dana-lista-liczb2), ktra reprezentuje pierwszy element listy przepracowanych
godzin; oraz
(3) (godziny->wynagrodzenia (rest dana-lista-liczb1) (rest dana-lista-liczb2)), ktra jest list
wynagrodze dla reszt list dana-lista-liczb1 i dana-lista-liczb2.
Aby otrzyma ostateczny wynik, musimy jedynie odpowiednio poczy te wartoci.
A dokadniej, zgodnie z opisem celu musimy obliczy wynagrodzenie dla pierwszego pracownika i skonstruowa list zoon z tej wartoci i wynagrodze pozostaych pracownikw. Oznacza to, e odpowied dla drugiej klauzuli wyraenia cond powinna wyglda nastpujco:
(cons (wynagrodzenie (first dana-lista-liczb1) (first dana-lista-liczb2))
(godziny->wynagrodzenia (rest dana-lista-liczb1) (rest dana-lista-liczb2)))
Zewntrzna funkcja wynagrodzenie pobiera dwa pierwsze elementy i oblicza odpowiednie wynagrodzenie. Listing 17.2 zawiera kompletne definicje obu funkcji.
Listing 17.2. Kompletna definicja funkcji godziny->wynagrodzenia
;; godziny->wynagrodzenia : lista-liczb lista-liczb -> lista-liczb
;; konstruuje now list zawierajc iloczyny odpowiednich
;; elementw list dana-lista-liczb1 i dana-lista-liczb2
;; ZAOENIE: listy maj rwn dugo

240

17. PRZETWARZANIE DWCH SKOMPLIKOWANYCH ELEMENTW DANYCH

(define (godziny->wynagrodzenia dana-lista-liczb1 dana-lista-liczb2)


(cond
((empty? dana-lista-liczb1) empty)
(else (cons (wynagrodzenie (first dana-lista-liczb1) (first dana-lista-liczb2))
(godziny->wynagrodzenia (rest dana-lista-liczb1) (rest dana-lista-liczb2))))))
;; wynagrodzenie : liczba liczba -> liczba
;; oblicza wynagrodzenie na podstawie danych liczb: stawka-godzinowa oraz
przepracowane-godziny
(define (wynagrodzenie stawka-godzinowa przepracowane-godziny)
( stawka-godzinowa przepracowane-godziny))

wiczenia
wiczenie 17.3. W rzeczywistym wiecie funkcja godziny->wynagrodzenia pobieraaby list struktur reprezentujcych pracownikw i list struktur reprezentujcych przebieg
prac w ostatnim miesicu. Struktura pracownika zawiera jego nazwisko, numer PESEL
oraz stawk godzinow. Struktura opisujca przebieg pracy zawiera nazwisko pracownika i liczb przepracowanych w danym miesicu godzin. Wynikiem jest lista struktur
zawierajcych nazwisko pracownika i nalene mu wynagrodzenie.
Zmodyfikuj funkcj z listingu 17.2 tak, aby pracowaa na powyszych klasach danych. Opracuj potrzebne definicje struktur i definicje danych. Zastosuj metod projektowania w procesie modyfikacji funkcji.
wiczenie 17.4. Opracuj funkcj zepnij, ktra pobierze list nazwisk oraz list numerw
telefonicznych i poczy je w list podobn do ksiki telefonicznej. Zakadajc, e mamy nastpujc definicj struktury:
(define-struct wpis (nazwisko numer))
pojedynczy wpis w ksice telefonicznej konstruujemy za pomoc instrukcji (make-wpis
s n), gdzie s jest symbolem, a n jest liczb. Za, e dane na wejciu listy maj identyczne
dugoci. Upro definicj na tyle, na ile bdzie to moliwe.

Jednoczesne przetwarzanie dwch list. Przypadek 3.


Oto trzeci opis problemu przedstawiony w formie kontraktu, opisu celu i nagwka:
;; wybierz-z-listy : lista-symboli N[>= 1] -> symbol
;; okrela n-ty symbol na licie dana-lista-symboli, liczc od 1;
;; sygnalizuje bd, jeli na danej licie nie ma n-tego symbolu
(define (wybierz-z-listy dana-lista-symboli n) )

JEDNOCZESNE PRZETWARZANIE DWCH LIST. PRZYPADEK 3.

241

Powyszy program wymaga opracowania funkcji, ktra bdzie pobiera liczb naturaln
i list symboli. Obie dane wejciowe nale do klas opisanych skomplikowanymi definicjami danych, jednak inaczej ni w dwch poprzednich problemach, klasy te s cakowicie rozczne. Na listingu 17.3 przypominamy obie definicje.
Listing 17.3. Definicje danych dla funkcji wybierz-z-listy
Definicje danych:
liczba naturalna [>=1] (N[>=1]) jest albo:
(1) 1, albo
(2) (dodaj1 n), jeli n naley do N[>=1].
lista-symboli jest albo:
(1) list pust, empty, albo
(2) (cons s ls), gdzie s jest symbolem, a ls jest list symboli.
Poniewa problem jest nietypowy, powinnimy upewni si, e nasze przykady
obejmuj wszystkie wane przypadki. Ten cel osigamy zazwyczaj wybierajc po jednym przykadzie dla kadej klauzuli z definicji i wybierajc losowo elementy dla pozostaych, prostych elementw danych. W tym przykadzie taka procedura prowadzi nas
do wybrania co najmniej dwch elementw dla danej lista-symboli i dwch dla N[>= 1].
Wybierzmy empty i (cons 'a empty) dla listy, oraz 1 i 3 dla liczb naturalnych. Po dwa
przykady dla obu argumentw oznaczaj, e bdziemy mieli ich cznie cztery, nie mamy
jednak danego wprost zwizku pomidzy tymi dwoma argumentami, ani adnych ogranicze wspomnianych w kontrakcie:
(wybierz-z-listy empty 1)
;; oczekiwane zachowanie:
(error 'wybierz-z-listy "")
(wybierz-z-listy (cons 'a empty) 1)
;; oczekiwana warto:
'a
(wybierz-z-listy empty 3)
;; oczekiwane zachowanie:
(error 'wybierz-z-listy "")
(wybierz-z-listy (cons 'a empty) 3)
;; oczekiwane zachowanie:
(error 'wybierz-z-listy "")
Tylko jeden z czterech wynikw jest symbolem; w pozostaych przypadkach otrzymalimy bdy zwizane z brakiem elementw na danych listach.

242

17. PRZETWARZANIE DWCH SKOMPLIKOWANYCH ELEMENTW DANYCH

Dyskusja o przykadach wykazaa, e istniej faktycznie cztery moliwe, niezalene


przypadki, ktre musimy bra pod uwag podczas projektowania funkcji. Moemy analizowa te przypadki za pomoc tabeli zawierajcej niezbdne warunki:
(empty? dana-lista-symboli)

(cons? dana-lista-symboli)

(= n 1)
(> n 1)
Wiersze tabeli opisuj dane wejciowe, dla ktrych funkcja wybierz-z-listy musi okreli,
co podano jako list symboli; w kolumnach rozrniamy dane liczby naturalne. Co wicej, w tabeli mamy cztery pola, z ktrych kade reprezentuje przypadek, w ktrym zarwno warunek odpowiedniej kolumny jak i wiersza ma warto true. Moemy to wyrazi za pomoc wyrae z operatorem and w odpowiednich komrkach tabeli:

(= n 1)
(> n 1)

(empty? dana-lista-symboli)
(and (= n 1) (empty? dana-lista-symboli))
(and (> n 1) (empty? dana-lista-symboli))

(cons? dana-lista-symboli)
(and (= n 1) (cons? dana-lista-symboli))
(and (> n 1) (cons? dana-lista-symboli))

atwo teraz wykaza, e dla dowolnej danej pary argumentw dokadnie jeden z czterech warunkw zawartych w komrkach tabeli powyej i ma warto true.
Korzystajc z naszej analizy przypadkw, moemy teraz zaprojektowa pierwsz
cz szablonu wyraenie warunkowe:
(define (wybierz-z-listy dana-lista-symboli n)
(cond
[(and (= n 1) (empty? dana-lista-symboli)) ]
[(and (> n 1) (empty? dana-lista-symboli)) ]
[(and (= n 1) (cons? dana-lista-symboli)) ]
[(and (> n 1) (cons? dana-lista-symboli)) ]))
Wyraenie cond sprawdza wszystkie cztery warunki wyrniajc wszystkie moliwoci.
Nastpnie, jeli to moliwe, musimy doda selektory do kadej klauzuli tego wyraenia:
(define (wybierz-z-listy dana-lista-symboli n)
(cond
[(and (= n 1) (empty? dana-lista-symboli))
]
[(and (> n 1) (empty? dana-lista-symboli))
(odejmij1 n) ]
[(and (= n 1) (cons? dana-lista-symboli))
(first dana-lista-symboli) (rest dana-lista-symboli)]
[(and (> n 1) (cons? dana-lista-symboli))
(odejmij1 n) (first dana-lista-symboli) (rest dana-lista-symboli) ]))

JEDNOCZESNE PRZETWARZANIE DWCH LIST. PRZYPADEK 3.

243

Dla liczby naturalnej n szablon zawiera co najwyej jeden selektor, ktry okrela poprzednika tej liczby w zbiorze liczb naturalnych. Dla listy dana-lista-symboli moliwe s
maksymalnie dwa selektory. Jednak w przypadku, w ktrym prawdziwy jest warunek
(= n 1) lub (empty? dana-lista-symboli), czyli jeden z dwch argumentw jest atomowy,
nie ma potrzeby stosowania odpowiadajcych tym danym wejciowym selektorw.
Ostatni krok w procesie konstruowania szablonu wymaga wypisania szablonu z zaznaczonymi rekursjami dla wyrae, w ktrych wyraenia selektorw zwracaj dane nalece do tej samej klasy, co dane wejciowe. W szablonie dla funkcji wybierz-z-listy takie
dziaanie ma sens jedynie dla ostatniej klauzuli cond, ktra zawiera wyraenia zarwno
dla N[>= 1], jak i dla listysymboli. Wszystkie inne klauzule zawieraj co najwyej jedno
odpowiednie wyraenie. Nie jest jednak do koca jasne, jak sformuowa w tym przypadku naturaln rekursj. Jeli zbagatelizujemy cel funkcji i w kroku konstruowania szablonu wypiszemy wszystkie moliwe rekursje, otrzymamy trzy przypadki:
(wybierz-z-listy (rest dana-lista-symboli) (odejmij1 n))
(wybierz-z-listy dana-lista-symboli (odejmij1 n))
(wybierz-z-listy (rest dana-lista-symboli) n)
Poniewa nie wiemy, ani ktra rekursja ma w tym przykadzie zastosowanie, ani czy
moemy wykorzysta wszystkie trzy rekursje, przechodzimy do nastpnego etapu.
Zgodnie z metod projektowania, przeanalizujmy kad z klauzul wyraenia cond
naszego szablonu i znajdmy prawidow odpowied na powysze pytanie:
(1) Jeli warunek (and (= n 1) (empty? dana-lista-symboli)) jest prawdziwy, funkcja wybierz-z-listy powinna wybra pierwszy element z pustej listy, co jest niemoliwe.
Odpowiedzi funkcji bdzie wic sygnalizacja o bdzie.
(2) Jeli warunek (and (> n 1) (empty? dana-lista-symboli)) jest prawdziwy, funkcja wybierz-z-listy powinna znowu wybra element z pustej listy. Odpowiedzi jest wic
znowu bd.
(3) Jeli warunek (and (= n 1) (cons? dana-lista-symboli)) jest prawdziwy, funkcja wybierz-z-listy powinna zwrci pierwszy element danej listy. Selektor (first danalista-symboli) przypomina nam, jak uzyska ten element. Wanie on bdzie odpowiedzi funkcji.
(4) W ostatniej klauzuli, jeli warunek (and (> n 1) (cons? dana-lista-symboli)) jest prawdziwy, musimy przeanalizowa, co zwracaj poszczeglne selektory:
(a) (first dana-lista-symboli) wybiera pierwszy element z listy symboli;
(b) (rest dana-lista-symboli) reprezentuje reszt listy; oraz
(c) (odejmij1 n) zwraca liczb mniejsz od jeden od danego indeksu listy.
Rozwamy przykad ilustrujcy znaczenie powyszych wyrae. Przypumy, e
funkcj wybierz-z-listy zastosowano dla listy (cons 'a (cons 'b empty)) i liczby 2:
(wybierz-z-listy (cons 'a (cons 'b empty)) 2)
Funkcja powinna zwrci symbol 'b, poniewa (first dana-lista-symboli) zwrci 'a,
natomiast (odejmij1 n) zwrci 1. Poniej przedstawiamy efekty ewentualnego zastosowania trzech naturalnych rekursji dla tych wartoci:

244

17. PRZETWARZANIE DWCH SKOMPLIKOWANYCH ELEMENTW DANYCH

(a) (wybierz-z-listy (cons 'b empty) 1) zwraca 'b, czyli podan warto;
(b) (wybierz-z-listy (cons 'a (cons 'b empty)) 1) zwraca warto 'a, ktra jest symbolem, ale nie jest oczekiwan wartoci dla naszego problemu;
(c) (wybierz-z-listy (cons 'b empty) 2) sygnalizuje bd, poniewa indeks jest wikszy ni dugo listy.
Powysza analiza sugeruje, e powinnimy uy wyraenia (wybierz-z-listy (cons 'b
empty) 1) jako odpowiedzi ostatniej klauzuli cond. Oparte na przykadzie rozwizania s jednak czsto zawodne, powinnimy wic sprbowa zrozumie, dlaczego
to wyraenie jest odpowiednie dla naszej funkcji.
Przypomnij sobie, e zgodnie z opisem celu,
(wybierz-z-listy (rest dana-lista-symboli) (odejmij1 n))
wybiera element o indeksie (n-1) z listy (rest dana-lista-liczb). Innymi sowy, zmniejszamy
indeks o 1, skracamy list o jeden element i szukamy w nowej licie elementu o zmniejszonym indeksie. Wyraenie zwraca warto zgodn z oczekiwaniami, podobnie jak
odpowied klauzuli z warunkiem (= n 1), przy zaoeniu, e dana-lista-symboli i n s
wartociami zoonymi. Nasz wybr odpowiedzi dla ostatniej klauzuli jest wic cakowicie uzasadniony. Kompletn definicj funkcji wybierz-z-listy przedstawia listing 17.4.
Listing 17.4. Kompletna definicja funkcji wybierz-z-listy
;; wybierz-z-listy : lista-symboli N[>= 1] -> symbol
;; okrela n-ty symbol na licie dana-lista-symboli, liczc od 1;
;; sygnalizuje bd, jeli na danej licie nie ma n-tego symbolu
(define (wybierz-z-listy dana-lista-symboli n)
(cond
[(and (= n 1) (empty? dana-lista-symboli)) (error 'wybierz-z-listy "lista jest za
krtka")]
[(and (> n 1) (empty? dana-lista-symboli)) (error 'wybierz-z-listy "lista jest za
krtka")]
[(and (= n 1) (cons? dana-lista-symboli)) (first dana-lista-symboli)]
[(and (> n 1) (cons? dana-lista-symboli)) (wybierz-z-listy (rest dana-lista-symboli)
(odejmij1 n))]))

wiczenia
wiczenie 17.5. Opracuj funkcj wybierz-z-listy0, ktra wybierze elementy z listy podobnie jak wybierz-z-listy, ale poczwszy od indeksu 0.
Przykady:
(symbol=? (wybierz-z-listy0 (list 'a 'b 'c 'd) 3)
'd)
(wybierz-z-listy0 (list 'a 'b 'c 'd) 4)
;; oczekiwane zachowanie:
(error 'wybierz-z-listy0 "lista jest za krtka")

UPRASZCZANIE FUNKCJI

245

Upraszczanie funkcji
Funkcja wybierz-z-listy zaprezentowana na listingu 17.4 jest bardziej skomplikowana ni
jest to konieczne. Pierwsza i druga klauzula wyraenia cond zwracaj takie same odpowiedzi: bd. Innymi sowy, jeli wyraenie:
(and (= n 1) (empty? dana-lista-symboli))
lub
(and (> n 1) (empty? dana-lista-symboli))
ma warto true, efektem dziaania funkcji jest bd. Moemy wic wykorzysta to podobiestwo i stworzy prostsze wyraenie cond:
(define (wybierz-z-listy dana-lista-symboli n)
(cond
[(or (and (= n 1) (empty? dana-lista-symboli))
(and (> n 1) (empty? dana-lista-symboli))) (error 'wybierz-z-listy "lista jest
za krtka")]
[(and (= n 1) (cons? dana-lista-symboli)) (first dana-lista-symboli)]
[(and (> n 1) (cons? dana-lista-symboli)) (wybierz-z-listy (rest dana-lista-symboli)
(odejmij1 n))]))
Nowe wyraenie jest prostym przeoeniem naszych obserwacji na jzyk Scheme.
Aby jeszcze bardziej uproci nasz funkcj, musimy zapozna si z regu algebraiczn dotyczc wartoci logicznych:
(or (and warunek1 dany-warunek)
(and warunek2 dany-warunek))
= (and (or warunek1 warunek2)
dany-warunek)
Powysze rwnanie nazywa si prawem de Morgana. Zastosowanie go w naszej funkcji
spowoduje nastpujce uproszczenie:
(define (wybierz-z-listy n dana-lista-symboli)
(cond
[(and (or (= n 1) (> n 1))
(empty? dana-lista-symboli)) (error 'wybierz-z-listy "lista jest za krtka")]
[(and (= n 1) (cons? dana-lista-symboli)) (first dana-lista-symboli)]
[(and (> n 1) (cons? dana-lista-symboli)) (wybierz-z-listy (rest dana-lista-symboli)
(odejmij1 n))]))
Rozwa teraz pierwsz cz warunku (or (= n 1) (> n 1)). Poniewa n naley do
zbioru N[>= 1], warunek jest zawsze prawdziwy. Gdybymy jednak zastpili go sowem
true, otrzymalibymy warunek:

246

17. PRZETWARZANIE DWCH SKOMPLIKOWANYCH ELEMENTW DANYCH

(and true
(empty? dana-lista-symboli))
ktry jest rwnowany z warunkiem (empty? dana-lista-symboli). Innymi sowy, funkcj
moemy zapisa w nastpujcy sposb:
(define (wybierz-z-listy dana-lista-symboli n)
(cond
[(empty? dana-lista-symboli) (error 'wybierz-z-listy "lista jest za krtka")]
[(and (= n 1) (cons? dana-lista-symboli)) (first dana-lista-symboli)]
[(and (> n 1) (cons? dana-lista-symboli)) (wybierz-z-listy (rest dana-lista-symboli)
(odejmij1 n))]))
Ta definicja jest znacznie prostsza ni ta, ktr zademonstrowalimy na listingu 17.4.
Moemy uproci nasz definicj jeszcze bardziej. Pierwszy warunek w ostatniej
wersji funkcji wybierz-z-listy odrzuca wszystkie przypadki, w ktrych dana-lista-symboli
jest pusta. Wyraenie (cons? dana-lista-symboli) w nastpnych dwch klauzulach bdzie
wic miao zawsze warto true. Jeli zastpimy warunek t wartoci i uprocimy wyraenie and, otrzymamy najprostsz z moliwych wersj funkcji wybierz-z-listy, ktr przedstawilimy na listingu 17.5. Mimo e ostatnia funkcja jest duo prostsza od oryginalnej,
wane jest, bymy rozumieli, e opracowalimy obie wersje w sposb systematyczny i tylko
dziki temu moemy by pewni, e dziaaj one poprawnie. Gdybymy prbowali od
pocztku tworzy wersj uproszczon, prdzej czy pniej popenilibymy bd.
Listing 17.5. Uproszczona definicja funkcji wybierz-z-listy
;; wybierz-z-listy : lista-symboli N[>= 1] -> symbol
;; okrela n-ty symbol na licie dana-lista-symboli, liczc od 1;
;; sygnalizuje bd, jeli na danej licie nie ma n-tego symbolu
(define (wybierz-z-listy dana-lista-symboli n)
(cond
[(empty? dana-lista-symboli) (error 'wybierz-z-listy "lista jest za krtka")]
[(= n 1) (first dana-lista-symboli)]
[(> n 1) (wybierz-z-listy (rest dana-lista-symboli) (odejmij1 n))]))

wiczenia
wiczenie 17.6. Opracuj funkcj zastap-empty-lista zgodnie ze strategi z podrozdziau
Jednoczesne przetwarzanie dwch list. Przypadek 2.. Nastpnie systematycznie upraszczaj definicj funkcji.
wiczenie 17.7. Upro definicj funkcji wybierz-z-listy0 z wiczenia 17.5 lub wyjanij,
dlaczego nie mona jej uproci.

PROJEKTOWANIE FUNKCJI POBIERAJCYCH DWIE ZOONE DANE WEJCIOWE

247

Projektowanie funkcji pobierajcych


dwie zoone dane wejciowe
Napotkamy czasem problemy, ktre wymagaj funkcji pobierajcych dwie zoone klasy
danych wejciowych. Najbardziej interesujce bd przypadki, w ktrych obie dane bd
miay nieznane rozmiary. Jak si przekonalimy w pierwszych trzech podrozdziaach,
moemy postpowa z takimi danymi wejciowymi na trzy rne sposoby.
Odpowiednim podejciem do tego typu problemw jest postpowanie zgodne z zaleceniami metody projektowania. Przede wszystkim musimy przeprowadzi analiz danych i zdefiniowa odpowiednie klasy danych. Nastpnie moemy stworzy kontrakt, opis
celu funkcji, ktre kolejno doprowadzaj nas do momentu, w ktrym moemy przej
do nastpnego kroku. Zanim to jednak zrobimy, powinnimy si zastanowi, z ktr z nastpujcych sytuacji mamy do czynienia:
(1) W niektrych przypadkach jeden z parametrw ma rol dominujc. I odwrotnie,
moemy traktowa jeden z parametrw jako atomowy fragment danych z punktu
widzenia opracowywanej funkcji.
(2) W innych przypadkach oba parametry s zsynchronizowane. Musz obejmowa
t sam klas wartoci o takiej samej strukturze. Np. jeli mamy dwie listy, to obie
musz mie tak sam dugo. Jeli mamy dwie strony WWW, musz one mie
tak sam dugo i jeli jedna z nich zawiera osadzon stron, druga rwnie
musi zawiera tak stron. Jeli decydujemy, e dwa parametry maj taki sam status
i musz by przetwarzane w sposb zsynchronizowany, moemy wybra jeden
z nich i zorganizowa funkcj wok niego.
(3) Wreszcie, w rzadkich przypadkach, moe nie by oczywistego zwizku pomidzy
dwoma parametrami. Dla takich danych wejciowych musimy analizowa wszystkie moliwe przypadki, zanim opracujemy przykady i zaprojektujemy szablon.
Dla pierwszych dwch przypadkw stosujemy istniejc metod projektowania. Ostatni
przypadek wymaga dodatkowych uwag.
Po tym, jak zdecydujemy, e funkcja naley do trzeciej kategorii, ale zanim opracujemy przykady i szablon funkcji, musimy opracowa dwuwymiarow tabel. Oto ponownie tabela dla funkcji wybierz-z-listy:
dana-lista-symboli
(empty? dana-lista-symboli)
n

(cons? dana-lista-symboli)

(= n 1)
(> n 1)

W kolumnach wyliczamy warunki rozrniajce podklasy pierwszego parametru, w wierszach wyliczamy warunki dla drugiego parametru.
Tabela pomaga w opracowaniu zarwno zbioru przykadw dla naszej funkcji, jak
i jej szablonu. Jeli chodzi o przykady, musz one pokrywa wszystkie moliwe przypadki. Oznacza to, e musimy opracowa przynajmniej po jednym przykadzie dla kadej komrki tabeli.

248

17. PRZETWARZANIE DWCH SKOMPLIKOWANYCH ELEMENTW DANYCH

Jeli chodzi o szablon, musimy w nim zawrze po jednej klauzuli wyraenia cond
dla kadej komrki. Kada z tych klauzul musi zawiera wszystkie moliwe selektory
dla obu parametrw. Jeli jeden z nich jest atomowy, nie ma oczywicie potrzeby stosowania selektorw. Wreszcie, zamiast pojedynczej naturalnej rekursji moe zaistnie konieczno wprowadzenia wielu rekursji. Dla funkcji wybierz-z-listy znalelimy trzy
przypadki. Generalnie wszystkie moliwe kombinacje selektorw s potencjalnymi kandydatami do wykorzystania w naturalnej rekursji. Poniewa nie moemy wiedzie, ktre
z nich s konieczne, a ktre nie s, wypisujemy je wszystkie i wybieramy te, ktre bd
odpowiednie dla naszej definicji funkcji.
Podsumowujc, projektowanie funkcji dla wielu parametrw opiera si na pewnej
odmianie starej metody projektowania. Kluczowe znaczenie ma przeoenie definicji danych na tabel demonstrujc wszystkie moliwe i interesujce nas kombinacje. Tworzenie przykadw dla funkcji i jej szablonu musi opiera si w jak najwikszym stopniu
wanie na tej tabeli. Wypenienie pustych przestrzeni w szablonie wymaga, jak zreszt
wszystkie pozostae czynnoci, praktyki.

wiczenia z przetwarzania
dwch zoonych danych wejciowych
wiczenia
wiczenie 17.8. Opracuj funkcj scalaj, ktra pobierze dwie listy liczb posortowane rosnco. Wynikiem funkcji bdzie pojedyncza, posortowana lista liczb zawierajca wszystkie liczby z obu list (i adnej innej). Poszczeglne liczby powinny wystpowa w licie
wyjciowej tyle razy, ile razy pojawiy si w dwch listach wejciowych.
Przykady:
(scalaj (list 1 3 5 7 9) (list 0 2 4 6 8))
;; oczekiwana warto:
(list 0 1 2 3 4 5 6 7 8 9)
(scalaj (list 1 8 8 11 12) (list 2 3 4 8 13 14))
;; oczekiwana warto:
(list 1 2 3 4 8 8 8 11 12 13 14)
wiczenie 17.9. Celem tego wiczenia jest opracowanie nowej wersji gry w szubienic
z rozdziau 6. dla sw o dowolnej dugoci.
Stwrz definicj danych reprezentujcych sowa dowolnej dugoci za pomoc list.
Litera powinna by reprezentowana przez symbole od 'a do 'z oraz symbol '_.
Opracuj funkcj odslon-liste, ktra pobierze trzy argumenty:
(1) Wybrane sowo, ktre naley odgadn.
(2) Sowo statusu, ktre okrela, jak du cz sowa odgadlimy do te pory.
(3) Liter, ktra reprezentuje nasz aktualn prb.

WICZENIA Z PRZETWARZANIA DWCH ZOONYCH DANYCH WEJCIOWYCH

249

Funkcja zwrci nowe sowo statusu, ktre skada si z dowolnych liter i znakw '_. Pola
w nowym sowie statusu okrelamy porwnujc prb z kad par liter ze sowa statusu
i wybranego sowa:
(1) Jeli prba jest rwna danej literze w wybranym sowie, wstawiamy t liter w odpowiednie miejsce w sowie statusu.
(2) W przeciwnym przypadku nowa litera odpowiada literze ze sowa statusu.
Przetestuj funkcj odslon-liste dla nastpujcych przykadw:
(odslon-liste (list 't 'e 'a) (list '_ 'e '_) 'u)
(odslon-liste (list 'a 'l 'e) (list 'a '_ '_) 'e)
(odslon-liste (list 'a 'l 'l) (list '_ '_ '_) 'l)
Okrel najpierw rcznie jakie powinny by rezultaty powyszych wywoa.
Zastosuj pakiet szkoleniowy hangman.ss i funkcje dorysuj-nastepna-czesc (patrz wiczenie 6.27) oraz odslon-liste, aby rozegra gr w szubienic. Oblicz take warto nastpujcego wyraenia:
(hangman-list odslon-liste dorysuj-nastepna-czesc)
Funkcja hangman-list (udostpniona we wspomnianym pakiecie nauczania) wybiera losowe sowo i wywietla okno z menu wyboru liter. Wybierz litery i gdy bdziesz gotowy,
kliknij przycisk Check, aby sprawdzi, czy Twj strza by trafny. Powodzenia!
wiczenie 17.10. Robotnicy w fabryce podbijaj swoje karty czasowe rano, gdy przychodz do pracy, i po poudniu gdy wychodz. Obecnie stosuje si elektroniczne karty
zawierajce numer pracownika i liczb przepracowanych godzin. Ponadto akta pracownika zawieraj zawsze jego nazwisko, numer i stawk godzinow.
Opracuj funkcj godziny->wynagrodzenia2, ktra pobierze list akt pracowniczych oraz
list (elektronicznych) kart. Funkcja bdzie oblicza miesiczne wynagrodzenie kadego
pracownika odpowiednio dopasowujc, na podstawie numeru pracownika, dane z jego
akt z danymi zapisanymi na karcie. Jeli zabraknie danej pary lub numery pracownikw
nie bd si zgadza, funkcja zatrzyma si z odpowiednim komunikatem o bdzie. Za,
e istnieje co najwyej jedna karta dla jednego pracownika i dla odpowiadajcemu mu
numeru.
Wskazwka: Ksigowy posortowaby najpierw obie listy wedug numerw pracownikw.
wiczenie 17.11. Kombinacja liniowa jest sum kilku skadnikw liniowych, co oznacza,
e zwraca zmienne i liczby. Te drugie nazywamy w tym kontekcie wspczynnikami.
Oto kilka przykadw:
5x
5 x + 17 y
5 x + 17 y + 3 z
We wszystkich trzech przykadach wspczynnikiem przy x jest 5, przy y jest liczba 17,
a jedynym przy z jest 3.

250

17. PRZETWARZANIE DWCH SKOMPLIKOWANYCH ELEMENTW DANYCH

Jeli mamy dane wartoci zmiennych, moemy okreli warto wielomianu. Np. jeli x = 10, wartoci iloczynu 5 x bdzie 50; jeli x = 10 i y = 1, wielomian 5 x + 17 y
przyjmie warto 67; jeli za x = 10, y = 1 i z = 2, wyraenie 5 x + 17 y + 3 z bdzie
miao warto 73.
W przeszoci opracowalibymy funkcje obliczajce wartoci liniowych kombinacji
dla poszczeglnych wartoci. Alternatywn reprezentacj takich wielomianw jest lista
wspczynnikw. Powysze kombinacje byyby reprezentowane przez takie listy:
(list 5)
(list 5 17)
(list 5 17 3)
Powysza reprezentacja zakada, e zgadzamy si zawsze uywa zmiennych w okrelonej kolejnoci.
Opracuj funkcj wartosc, ktra pobierze reprezentacj wielomianu (lista wspczynnikw) oraz list liczb (wartoci zmiennych). Obie listy maj t sam dugo. Funkcja
powinna zwrci warto tego wielomianu dla danych wartoci zmiennych.
wiczenie 17.12. Ewa, Joanna, Dorota i Maria s siostrami, ktre chciayby zaoszczdzi
pienidze i ograniczy wysiek zwizany z kupowaniem prezentw gwiazdkowych. Postanowiy wic przeprowadzi losowanie, ktre przypisze kadej z nich jedn osob, ktra
nastpnie zostanie obdarowana prezentem. Poniewa Joanna jest programist komputerowym, siostry poprosiy j o napisanie programu, ktry przeprowadzi losowanie w sposb bezstronny. Program nie moe oczywicie przypisa adnej siostrze jej samej jako
odbiorcy prezentu.
Oto definicja funkcji wybierz-prezent, ktra pobiera list rnych imion (symboli) i wybiera losowo jeden z ukadw listy, w ktrym aden z elementw nie pozosta na swoim
miejscu:
;; wybierz-prezent: lista-imion -> lista-imion
;; wybiera "losowy", inny ni oryginalny ukad imion
(define (wybierz-prezent imiona)
(wybierz-losowo
(nie-takie-same imiona (uklady imiona))))
Przypomnij sobie podobn funkcj z wiczenia 12.6, ktra pobieraa list symboli i zwracaa list wszystkich moliwych ukadw zoonych z elementw tej listy.
Opracuj zewntrzne funkcje:
(1) wybierz-losowo : lista-list-imion -> lista-imion, ktra pobierze list elementw i losowo wybierze jeden z nich;
(2) nie-takie-same : lista-imion lista-list-imion -> lista-list-imion, ktra pobierze list imion
L oraz list ukadw i zwrci list takich ukadw, w ktrych adne imi nie wystpuje na takiej samej pozycji co w danej licie imion.
Dwie permutacje s ze sob zgodne na pewnej pozycji, jeli moemy pobra to
samo imi z obu list za pomoc sowa first lub takiej samej liczby sw rest. Np. listy (list 'a 'b 'c) oraz (list 'c 'a 'b) nie s ze sob zgodne; natomiast listy (list 'a 'b 'c)
i (list 'c 'b 'a) zgadzaj si ze sob na drugiej pozycji. Moemy to udowodni stosujc dla obu list operacj rest poprzedzajc first.

ROZSZERZONE WICZENIE: OBLICZANIE WYRAE JZYKA SCHEME. CZ 2.

251

Postpuj ostronie i zgodnie z odpowiedni metod projektowania dla kadej klauzuli.


Wskazwka: Przypomnij sobie, e funkcja (random n) wybiera losow liczb od 0 do n
(patrz take wiczenie 11.5).
wiczenie 17.13. Opracuj funkcj prefiksDNA. Funkcja pobierze dwa argumenty bdce
listami symboli (w DNA wystpuj jedynie 'a, 'c, 'g oraz 't, ale moemy to ograniczenie
na razie pomin). Pierwsza lista nazywana jest wzorcem, druga szukanym acuchem.
Funkcja zwraca warto true, jeli wzorzec jest prefiksem szukanego acucha. We wszystkich innych przypadkach funkcja powinna zwrci warto false.
Przykady:
(PrefiksDNA (list 'a 't) (list 'a 't 'c))
(not (PrefiksDNA (list 'a 't) (list 'a)))
(PrefiksDNA (list 'a 't) (list 'a 't))
(not (PrefiksDNA (list 'a 'c 'g 't) (list 'a 'g)))
(not (PrefiksDNA (list 'a 'a 'c 'c) (list 'a 'c)))
Jeli to moliwe, upro funkcj PrefiksDNA.
Zmodyfikuj funkcj tak, aby zwracaa pierwszy element szukanego acucha, ktry
nie znalaz si we wzorcu, jeli oczywicie wzorzec jest prawidowym prefiksem szukanego acucha. Jeli listy do siebie nie pasuj lub wzorzec jest duszy od szukanego acucha, zmodyfikowana funkcja powinna nadal zwraca false. Jeli listy s tej samej dugoci i pasuj do siebie, wynikiem powinno by nadal true.
Przykady:
(symbol=? (PrefiksDNA (list 'a 't) (list 'a 't 'c))
'c)
(not (PrefiksDNA (list 'a 't) (list 'a)))
(PrefiksDNA (list 'a 't) (list 'a 't))
Czy ten wariant funkcji PrefiksDNA moe by uproszczony? Jeli tak, zrb to. Jeli nie,
wyjanij dlaczego.

Rozszerzone wiczenie:
obliczanie wyrae jzyka Scheme. Cz 2.
Celem tego podrozdziau jest rozszerzenie moliwoci programu stworzonego w rozdziale 14. (podrozdzia Rozszerzone wiczenie: obliczanie wyrae jzyka Scheme) tak,
by mg radzi sobie z wywoaniami i definicjami funkcji. Innymi sowy, nowy program
powinien symulowa, co staoby si w rodowisku DrScheme, gdybymy wpisali dane
wyraenie w oknie Interactions i kliknli przycisk Execute. Aby uproci sobie zadanie,
zakadamy, e wszystkie funkcje zdefiniowane w oknie Definitions pobieraj po jednym
argumencie.

252

17. PRZETWARZANIE DWCH SKOMPLIKOWANYCH ELEMENTW DANYCH

wiczenia
wiczenie 17.14. Rozszerz definicj danych z wiczenia 14.17 tak, aby byo moliwe reprezentowanie wywoa funkcji w wyraeniach. Wywoanie powinno by reprezentowane jako struktura z dwoma polami. Pierwsze pole zawiera nazw funkcji, drugie
jedn reprezentacj wyraenia bdcego argumentem funkcji.
Kompletny program obliczajcy wartoci wyrae powinien obsugiwa take definicje funkcji.
wiczenie 17.15. Opracuj definicj struktury i definicj danych dla definicji funkcji.
Przypomnij sobie, e definicja funkcji zawiera trzy istotne atrybuty:
(1) Nazw funkcji.
(2) Nazw parametru.
(3) Ciao funkcji.
Taka charakterystyka funkcji sugeruje wprowadzenie struktury z trzema polami. Pierwsze dwa zawieraj symbole, ostatni reprezentuje ciao funkcji, ktre jest wyraeniem.
Prze nastpujce definicje na wartoci w jzyku Scheme:
(define (f x) (+ 3 x))
(define (g x) ( 3 x))
(define (h u) (f ( 2 u)))
(define (i v) (+ ( v v) ( v v)))
(define (k w) ( (h w) (i w)))
Opracuj wicej przykadw i podobnie prze je na nasz reprezentacj.
wiczenie 17.16. Opracuj funkcj interpretuj-z-jedna-definicja. Funkcja pobierze reprezentacj wyraenia Scheme i reprezentacj definicji funkcji P.
Pozostae wyraenia z wiczenia 14.17 powinny by interpretowane jak wczeniej.
W przypadku pojawienia si reprezentacji zmiennej w wyraeniu funkcja interpretuj-zjedna-definicja powinna zasygnalizowa bd. Dla wywoania funkcji P w wyraeniu funkcja interpretuj-z-jedna-definicja powinna:
(1) obliczy warto argumentu;
(2) zastpi wszystkie wystpienia parametru funkcji P w jej ciele wartoci obliczonego w poprzednim kroku argumentu; oraz
(3) obliczy nowe wyraenie za pomoc rekursji. Oto szkic takiego dziaania:1
(oblicz-z-jedna-definicja (zastp )
dana-definicja-funkcji)
Dla wszystkich innych wywoa funkcja interpretuj-z-jedna-definicja powinna sygnalizowa bd.
1

Omwimy szczegowo t form rekursji w czci V.

253

RWNO I TESTOWANIE

wiczenie 17.17. Opracuj funkcj interpretuj-z-definicjami. Funkcja pobierze reprezentacj


wyraenia Scheme i list reprezentacji definicji funkcji definicje. Funkcja powinna
zwrci liczb, jak rodowisko DrScheme wywietlioby w oknie Interactions, gdybymy
wpisali wyraenie reprezentowane przez pierwszy parametr w tym oknie, za okno Definitions zawieraoby, reprezentowane przez drugi parametr, definicje funkcji.
Pozostae wyraenia z wiczenia 14.17 powinny by interpretowane jak wczeniej.
Dla wywoania funkcji P w wyraeniu funkcja interpretuj-z-definicjami powinna:
(1) obliczy warto argumentu;
(2) znale definicj odpowiedniej funkcji na licie definicje;
(3) zastpi wszystkie wystpienia parametru funkcji P w jej ciele wartoci obliczonego w pierwszym kroku argumentu; oraz
(4) obliczy nowe wyraenie za pomoc rekursji.
Podobnie jak DrScheme, funkcja interpretuj-z-definicjami sygnalizuje bd w przypadku
wywoania funkcji, ktrej nazwy nie ma na licie, oraz w przypadku odwoania si do
reprezentacji zmiennej w wyraeniu.

Rwno i testowanie
Wiele opracowanych przez nas funkcji zwraca listy. Kiedy je testujemy, musimy porwnywa dwie listy: wyniki zwracane przez funkcje z przewidywanymi wartociami. Porwnywanie list rcznie jest nudne i nie daje pewnoci, e nie popenilimy bdu.
Opracujmy funkcj, ktra pobiera dwie listy liczb i okrela, czy s sobie rwne:
;; lista=? : lista-liczb lista-liczb -> boolean
;; okrela, czy dana-lista i inna-lista
;; zawieraj te same liczby w tym samym porzdku
(define (lista=? dana-lista inna-lista) )
Opis celu ulepsza oglne przeznaczenie funkcji i przypomina nam, e o ile klienci mog
uwaa dwie listy za rwne, jeli zawieraj te same elementy, niezalenie od kolejnoci,
to programici s bardziej dokadni i wczaj kolejno elementw jako element porwnania. Kontrakt i opis celu pokazuj take, e lista=? jest funkcj przetwarzajc dwie
skomplikowane wartoci i w rzeczywistoci to nas najbardziej interesuje.
Porwnywanie dwch list oznacza, e musimy przejrze wszystkie elementy obu list.
Eliminuje to moliwo projektowania funkcji lista=? linia po linii, jak w przypadku funkcji
zastap-empty-lista z podrozdziau Jednoczesne przetwarzanie dwch list. Przypadek 1..
Na pierwszy rzut oka nie istnieje aden zwizek pomidzy dwiema listami wejciowymi,
co sugeruje, e powinnimy wykorzysta zmodyfikowan metod projektowania.
Zacznijmy wic od tabeli:
(empty? dana-lista)
(empty? inna-lista)
(cons? inna-lista)

(cons? dana-lista)

254

17. PRZETWARZANIE DWCH SKOMPLIKOWANYCH ELEMENTW DANYCH

Tabela ma cztery komrki do wypenienia, co oznacza, e potrzebujemy (przynajmniej)


czterech testw i czterech klauzul wyraenia cond w szablonie.
Oto pi testw:
(lista=? empty empty)
(not
(lista=? empty (cons 1 empty)))
(not
(lista=? (cons 1 empty) empty))
(lista=? (cons 1 (cons 2 (cons 3 empty)))
(cons 1 (cons 2 (cons 3 empty))))
(not
(lista=? (cons 1 (cons 2 (cons 3 empty)))
(cons 1 (cons 3 empty))))
Drugi i trzeci pokazuj, e lista=? musi obsugiwa swoje argumenty symetrycznie. Dwa
ostatnie testy pokazuj natomiast, dla jakich danych wejciowych funkcja lista=? powinna
zwraca true lub false.
Trzy z czterech klauzul cond zawieraj selektory, natomiast jedna z nich zawiera
naturalne rekursje:
(define (lista=? dana-lista inna-lista)
(cond
[(and (empty? dana-lista) (empty? inna-lista)) ]
[(and (cons? dana-lista) (empty? inna-lista))
(first dana-lista) (rest dana-lista) ]
[(and (empty? dana-lista) (cons? inna-lista))
(first inna-lista) (rest inna-lista) ]
[(and (cons? dana-lista) (cons? inna-lista))
(first dana-lista) (first inna-lista)
(lista=? (rest dana-lista) (rest inna-lista))
(lista=? dana-lista (rest inna-lista))
(lista=? (rest dana-lista) inna-lista) ]))
W czwartej klauzuli mamy trzy naturalne rekursje, poniewa moemy poczy parami
dwa selektory oraz moemy poczy w pary kady parametr z jednym selektorem.
Od powyszego szablonu do kompletnej definicji dzieli nas jedynie niewielki krok.
Dwie listy mog zawiera te same elementy tylko wtedy, gdy obie s puste lub skonstruowane za pomoc instrukcji cons. Ten warunek natychmiast sugeruje warto true
jako odpowied dla pierwszej klauzuli oraz false dla dwch nastpnych. W ostatniej
klauzuli mamy dwie liczby bdce pierwszymi elementami obu list oraz trzy naturalne
rekursje. Musimy porwna te dwie liczby. Co wicej, wyraenie (lista=? (rest dana-lista)
(rest inna-lista)) oblicza, czy reszty obu list s identyczne. Dwie listy s sobie rwne wtedy i tylko wtedy, gdy spenione s oba warunki, co oznacza, e musimy je poczy za
pomoc operatora logicznego and:

RWNO I TESTOWANIE

255

(define (lista=? dana-lista inna-lista)


(cond
[(and (empty? dana-lista) (empty? inna-lista)) true]
[(and (cons? dana-lista) (empty? inna-lista)) false]
[(and (empty? dana-lista) (cons? inna-lista)) false]
[(and (cons? dana-lista) (cons? inna-lista))
(and (= (first dana-lista) (first inna-lista))
(lista=? (rest dana-lista) (rest inna-lista)))]))
Dwie pozostae naturalne rekursje nie odgrywaj dla naszego rozwizania adnej roli.
Spjrzmy po raz drugi na zwizki pomidzy dwoma parametrami. Pierwszy sposb, w jaki rozwizalimy problem porwnywania list, sugeruje, e jeli dwie listy maj
by sobie rwne, to drugi parametr musi mie identyczny ksztat jak pierwszy. Inaczej
mwic, moglibymy opracowa funkcj opart na strukturze pierwszego parametru
i sprawdzajc w razie potrzeby struktur innego parametru.
Pierwszy parametr jest list liczb, moemy wic ponownie wykorzysta szablon
funkcji przetwarzajcych listy:
(define (lista=? dana-lista inna-lista)
(cond
[(empty? dana-lista) ]
[(cons? dana-lista)
(first dana-lista) (first inna-lista)
(lista=? (rest dana-lista) (rest inna-lista)) ]))
Jedyn rnic jest to, e druga klauzula przetwarza drugi parametr w taki sam sposb
jak pierwszy. Takie rozwizanie bardzo przypomina funkcj godziny->wynagrodzenia z podrozdziau Jednoczesne przetwarzanie dwch list. Przypadek 2..
Wypenienie wolnych przestrzeni w szablonie jest trudniejsze ni w pierwszej prbie
rozwizania tego problemu. Jeli dana-lista jest pusta, odpowied zaley od drugiej danej
wejciowej: inna-lista. Jak pokazuj przykady, odpowiedzi bdzie w tym przypadku true
wtedy i tylko wtedy, gdy inna-lista rwnie bdzie list pust. Przekadajc to na jzyk
Scheme, otrzymamy nastpujc odpowied dla pierwszej klauzuli: (empty? inna-lista).
Jeli dana-lista nie jest pusta, szablon sugeruje, e powinnimy obliczy odpowied
funkcji na podstawie:
(1) (first dana-lista), pierwsza liczba na licie dana-lista;
(2) (first inna-lista), pierwsza liczba na licie inna-lista;
(3) (lista=? (rest dana-lista) (rest inna-lista)), wyraenie, ktre okrela, czy reszty obu
list s sobie rwne.
Majc dany opis celu funkcji i przykady jej dziaania, moemy po prostu porwna
elementy (first dana-lista) oraz (first inna-lista) i poczy wynik z naturaln rekursj za
pomoc operacji and:
(and (= (first dana-lista) (first inna-lista))
(lista=? (rest dana-lista) (rest inna-lista)))

256

17. PRZETWARZANIE DWCH SKOMPLIKOWANYCH ELEMENTW DANYCH

Mimo e wykonany przez nas krok wyglda na prosty, jego efektem jest niepoprawna
definicja. Celem wypisania warunkw w wyraeniu cond jest upewnienie si, e wszystkie selektory s poprawne.
aden element w specyfikacji funkcji lista=? nie sugeruje jednak, e inna-lista jest
skonstruowana za pomoc instrukcji cons, jeli dana-lista jest skonstruowana za pomoc
tej samej instrukcji.
Moemy poradzi sobie z tym problemem za pomoc dodatkowego warunku:
(define (lista=? dana-lista inna-lista)
(cond
[(empty? dana-lista) (empty? inna-lista)]
[(cons? dana-lista)
(and (cons? inna-lista)
(and (= (first dana-lista) (first inna-lista))
(lista=? (rest dana-lista) (rest inna-lista))))]))
Dodatkowym warunkiem jest (cons? inna-lista), co oznacza, e lista=? zwrci false, jeli
warunek (cons? dana-lista) bdzie prawdziwy oraz (cons? inna-lista) bdzie faszywy. Jak
pokazuj przykady, taki wanie powinien by podany efekt.
Podsumowujc, funkcja lista=? pokazuje, e czasami moemy zastosowa wicej ni
jedn metod projektowania w celu opracowania danej funkcji. Efekty prac s rne,
mimo e s ze sob blisko powizane; faktycznie, moglibymy udowodni, e obie funkcje zwracaj zawsze takie same wyniki dla tych samych danych wejciowych. Podczas
drugiego procesu tworzenia funkcji wykorzystalimy take spostrzeenia z pierwszej
prby.

wiczenia
wiczenia 17.18. Przetestuj obie wersje funkcji lista=?.
wiczenie 17.19. Upro pierwsz wersj funkcji lista=?. Oznacza to, e powiniene poczy ssiadujce klauzule wyraenia cond, ktre zwracaj takie same wyniki, czc
ich warunki za pomoc operatora or. Jeli to konieczne, poprzestawiaj klauzule i uyj
sowa else w ostatniej klauzuli w ostatecznej wersji funkcji.
wiczenie 17.20. Opracuj funkcj sym-lista=?. Funkcja okreli, czy dwie listy symboli s
sobie rwne.
wiczenie 17.21. Opracuj funkcj zawiera-te-same-liczby, ktra okreli, czy dwie listy liczb
zawieraj te same liczby, niezalenie od ich kolejnoci. Np. wyraenie:
(zawiera-te-same-liczby (list 1 2 3) (list 3 2 1))
zwrci warto true.
wiczenie 17.22. Klasy liczb, symboli i wartoci logicznych nazywamy czasami atomami:2
2

Niektrzy wczaj do tej klasy take warto empty i pojedyncze znaki.

RWNO I TESTOWANIE

257

atom jest albo:


(1) liczb;
(2) wartoci logiczn (boolean);
(3) symbolem.
Opracuj funkcj rowne-listy?, ktra pobierze dwie listy atomw i okreli, czy s sobie
rwne.
Porwnanie obu wersji funkcji lista=? sugeruje, e druga wersja jest atwiejsza do
zrozumienia od pierwszej. Stwierdzamy w niej, e dwie zoone wartoci s sobie rwne,
jeli druga jest stworzona za pomoc tego samego konstruktora co pierwsza oraz jeli elementy wykorzystane w tym konstruktorze s takie same. Ten pomys mona wykorzysta podczas opracowywania innych funkcji porwnujcych ze sob dane wejciowe.
Aby potwierdzi nasze przypuszczenie, spjrzmy na funkcj porwnujc strony
WWW:
;; www=? : strona-www strona-www -> boolean
;; okrela, czy dana-strona i inna-strona maj taki sam ksztat drzewa
;; i zawieraj te same symbole uoone w tym samym porzdku
(define (www=? dana-strona inna-strona) )
Przypomnij sobie definicj dla prostych stron WWW:
strona-WWW (w skrcie SW) jest albo:
(1) empty;
(2) (cons s sw), gdzie s jest symbolem, za sw jest stron WWW;
(3) (cons esw sw), gdzie esw i sw s stronami WWW.
Definicja danych zawiera trzy klauzule, co oznacza, e jeli chcielibymy opracowa funkcj www=? zgodnie ze zmodyfikowan metod projektowania, musielibymy przestudiowa dziewi przypadkw. Wykorzystujc zamiast tego dowiadczenie zdobyte podczas tworzenia funkcji lista=?, moemy rozpocz prac od prostego szablonu dla stron
WWW:
(define (www=? dana-strona inna-strona)
(cond
[(empty? dana-strona) ]
[(symbol? (first dana-strona))
(first dana-strona) (first inna-strona)
(www=? (rest dana-strona) (rest inna-strona)) ]
[else
(www=? (first dana-strona) (first inna-strona))
(www=? (rest dana-strona) (rest inna-strona)) ]))

258

17. PRZETWARZANIE DWCH SKOMPLIKOWANYCH ELEMENTW DANYCH

W drugiej klauzuli wyraenia cond ponownie musimy postpowa podobnie jak w przypadku funkcji godziny->wynagrodzenia i lista=?. Oznacza to, e mwimy, i inna-strona
musi mie taki sam ksztat co dana-strona, jeli ma by identyczna i mamy przetwarza obie
strony w analogiczny sposb. Rozumowanie dla drugiej klauzuli jest podobne.
W miar ulepszania powyszego szablonu musimy znowu doda warunki zwizane
z parametrem inna-strona, aby upewni si, e odpowiednie selektory bd dziaa poprawnie:
(define (www=? dana-strona inna-strona)
(cond
[(empty? dana-strona) (empty? inna-strona)]
[(symbol? (first dana-strona))
(and (and (cons? inna-strona) (symbol? (first inna-strona)))
(and (symbol=? (first dana-strona) (first inna-strona))
(www=? (rest dana-strona) (rest inna-strona))))]
[else
(and (and (cons? inna-strona) (list? (first inna-strona)))
(and (www=? (first dana-strona) (first inna-strona))
(www=? (rest dana-strona) (rest inna-strona))))]))
Musimy zwaszcza upewni si w drugiej i trzeciej klauzuli, e inna-strona jest skonstruowan list, oraz e jej pierwszy element jest symbolem lub list. W przeciwnym przypadku funkcja byaby analogiczna z funkcj lista=? i dziaaaby w identyczny sposb.

wiczenia
wiczenie 17.23. Narysuj tabel opart na definicji danych dla prostej strony WWW.
Opracuj przynajmniej po jednym przykadzie dla kadego z dziewiciu przypadkw.
Przetestuj funkcj www=? dla tych przykadw.
wiczenie 17.24. Opracuj funkcj posn=?, ktra pobiera dwie struktury posn i okrela,
czy s identyczne.
wiczenie 17.25. Opracuj funkcj drzewo=?, ktra pobierze dwa drzewa binarne i okreli,
czy s identyczne.
wiczenie 17.26. Przeanalizuj ponisze dwie wzajemnie rekursywne definicje danych:
s-lista jest albo:
(1) list pust, empty, albo
(2) (cons s sl), gdzie s jest s-wyr, za sl jest list s-lista.
s-wyr jest albo:
(1)
(2)
(3)
(4)

liczb,
wartoci logiczn,
symbolem,
list s-lista.

RWNO I TESTOWANIE

259

Opracuj funkcj s-lista=?, ktra pobiera dwie listy s-lista i okrela, czy s identyczne. Podobnie jak w przypadku list liczb, dwie listy zgodne z definicj klasy s-lista s sobie
rwne, jeli zawieraj te same elementy na analogicznych pozycjach.
Skoro przeanalizowalimy ju problem rwnoci pewnych wartoci, moemy wrci do oryginalnego rda rozwaa w tym rozdziale: funkcji testujcych. Przypumy,
e chcemy przetestowa funkcj godziny->wynagrodzenia z podrozdziau Jednoczesne
przetwarzanie dwch list. Przypadek 2.:
(godziny->wynagrodzenia (cons 5.65 (cons 8.75 empty))
(cons 40 (cons 30 empty)))
= (cons 226.0 (cons 262.5 empty))
Jeli po prostu wpiszemy wywoanie tej funkcji w oknie Interactions lub dodamy je na
kocu okna Definitions, musimy rcznie porwna otrzymany wynik z przewidywan
wartoci. Dla krtkich list, podobnych do powyszej, jest to moliwe; dla dugich list,
gbokich stron WWW lub innych duych danych zoonych rczne porwnywanie moe by rdem bdw.
Korzystajc z funkcji porwnujcych podobnych do lista=?, moemy znacznie zredukowa konieczno rcznego porwnywania wynikw testw. W naszym obecnym
przypadku moemy doda nastpujce wyraenie:
(lista=?
(godziny->wynagrodzenia (cons 5.65 (cons 8.75 empty))
(cons 40 (cons 30 empty)))
(cons 226.0 (cons 262.5 empty)))
na kocu okna Definitions. Jeli klikniemy teraz przycisk Execute, musimy tylko odczyta
w oknie Interactions, czy wszystkie podobne testy zwrciy warto true.
W rzeczywistoci moemy i jeszcze dalej. Moemy napisa funkcj testujc podobn do tej z listingu 17.6. Klasa wynik-testow skada si z wartoci i listy czterech elementw: acucha "ze wyniki testw:" i trzech list. Korzystajc z naszej nowej zewntrznej funkcji, moemy przetestowa godziny->wynagrodzenia w sposb nastpujcy:
(testuj-godziny->wynagrodzenia
(cons 5.65 (cons 8.75 empty))
(cons 40 (cons 30 empty))
(cons 226.0 (cons 262.5 empty)))
Listing 17.6. Funkcja testujca
;; testuj-godziny->wynagrodzenia : lista-liczb lista-liczb lista-liczb -> wynik-testow
;; testuje funkcj godziny->wynagrodzenia
(define (testuj-godziny->wynagrodzenia dana-lista inna-lista oczekiwany-wynik)
(cond
[(lista=? (godziny->wynagrodzenia dana-lista inna-lista) oczekiwany-wynik)
true]
[else
(list "ze wyniki testw:" dana-lista inna-lista oczekiwany-wynik)]))

260

17. PRZETWARZANIE DWCH SKOMPLIKOWANYCH ELEMENTW DANYCH

Jeli co nie zadziaa poprawnie w naszych testach, wspomniana czteroelementowa lista


okreli dokadnie, w ktrym przypadku wynik rni si od oczekiwanego.
Testowanie za pomoc rwnoci? Twrcy jzyka Scheme przewidzieli konieczno stosowania oglnej funkcji porwnujcej dane i udostpnili j:
;; equal? : dowolna-wartosc dowolna-wartosc -> boolean
;; okrela, czy dwie wartoci s strukturalnie identyczne
;; i zawieraj te same wartoci atomowe na analogicznych pozycjach
Jeli stosujemy equal? dla dwch list, funkcja porwnuje je w taki sam sposb, jak robia
to funkcja lista=?; kiedy dajemy na wejciu funkcji equal? par struktur, to funkcja porwnuje kolejno odpowiednie pola, jeli obie dane nale do tego samego typu struktur;
jeli natomiast uruchomimy funkcj equal? dla dwch danych atomowych, dane te zostan porwnane za pomoc =, symbol=? lub boolean=?, w zalenoci od ich typu.

Wskazwka dotyczca testowania


Uywaj funkcji equal? w procesie testowania (jeli konieczne jest porwnywanie
wartoci).
Nieposortowane listy: W niektrych przypadkach stosujemy listy, mimo e porzdek
elementw nie gra roli. Wane jest wwczas posiadanie takich funkcji, jak zawiera-tesame-liczby (patrz wiczenie 17.21), jeli chcemy okreli, czy wyniki wywoania jakiej
funkcji zawieraj odpowiednie elementy.

wiczenia
wiczenie 17.27. Zdefiniuj, za pomoc funkcji equal?, funkcj testujc funkcj zastapempty-lista z podrozdziau Jednoczesne przetwarzanie dwch list. Przypadek 1.. Sformuuj take przykady bdce przypadkami testowymi w tej funkcji.
wiczenie 17.28. Zdefiniuj funkcj testuj-wybierz-z-listy, ktra bdzie zarzdza przypadkami testowymi dla funkcji wybierz-z-listy z podrozdziau Jednoczesne przetwarzanie dwch list. Przypadek 1.. Sformuuj przykady z rozdziau jako przypadki testowe
dla funkcji testuj-wybierz-z-listy.
wiczenie 17.29. Zdefiniuj funkcj testuj-interpretuj, ktra bdzie przeprowadza testy
funkcji interpretuj-z-definicjami za pomoc funkcji equal?. Sformuuj ponownie przypadki
testowe za pomoc nowej funkcji.

You might also like