You are on page 1of 236

Милан Гњатовић

Концепти функционалног и
императивног програмирања ић
.
ов

а.
ат

ан
Гњ

ж
др
ан

за
ил

су
М

а
1.

ав
02

пр
–2

а
20

Св
20

а.
©

иj
рз
ве
на

©2020–2021. Милан Гњатовић.


д
Ра

Сва права задржана. Забрањено прештампавање и копирање. Немоjте


цитирати ни референцирати без дозволе аутора.

Ово jе радна верзиjа књиге.


Коментаре можете слати на: milan.gnjatovic@kpu.edu.rs.
©
20
20
–2
02
Ра 1.
д М
на ил
ве ан
рз Гњ
иj ат
а.
Св ов
а ић
.
пр
ав
а
су
за
др
ж
ан
а.
©
20
20
–2
02
Ра 1.
д М
на ил
ве ан
рз Гњ
иj ат
а.
Св ов
а ић
.
пр
ав
а
су
за
Душану, Ани, Петру и Лени

др
ж
ан
а.
©
20
20
–2
02
Ра 1.
д М
на ил
ве ан
рз Гњ
иj ат
а.
Св ов
а ић
.
пр
ав
а
су
за
др
ж
ан
а.
Предговор аутора

.
ић
Књиге из програмирања неоправдано често полазе од претпоставке да
ов
jе програмирање занатска вештина. Такво редуковање поjма програми-

а.
рања не само да jе неправедно према информатици као грани науке, већ
ат

ан
доводи до тога да се „вештина” програмирања представља кроз призму
Гњ

ж
програмских jезика, стављаjући синтаксичке детаље у фокус пажње, и

др
остављаjући читаоца ускраћеног за увид у фундаменталне концепте про-
ан

грамирања. за
У овоj књизи примењен jе другачиjи приступ. Ако тражите детаљну
ил

су
спецификациjу синтаксе неког програмског jезика, нећете jе наћи — мада
М

ћете видети довољно програмских ко̂дова да стекнете осећаj за интерпре-


а

тирање програмских синтаксичких структура. У основи, главна намена


1.

ав

ове књиге jе да вам представи концепте функционалног и императивног


02

пр

програмирања. Попут свих других инжењерских дисциплина, програ-


–2

мирање подразумева начин размишљања. Функционално и императивно


а
20

програмирање представљаjу две фундаменталне парадигме програмира-


Св

ња, што значи да су у књизи представљена два различита, али повезана


20

начина размишљања о програмирању. Концепти функционалног програ-


а.
©

мирања илустровани су на програмском jезику Ракет (енгл. Racket), а


иj

концепти императивног програмирања на програмском jезику Ц (енгл.


рз

C ). Међутим, изложени концепти нису ограничени на ове програмске


ве

jезике.
Први део књиге посвећен jе функционалном програмирању, што ни-
на

jе случаjни избор. Функционална парадигма програмирања често jе за-


д

немарена у уводним курсевима програмирања, због предубеђења да се


Ра

ова парадигма примењуjе само у интелектуалном вакууму академских


дискусиjа, док jе императивна парадигма од интереса за практичне при-
мене. Последично, може се очекивати да читалац поседуjе неко пред-
знање о императивном програмирању (коjе, наравно, ниjе предуслов за
разумевање ове књиге). Да jе књига започела разматрањем концепата
императивног програмирања, то би само додатно утврдило читаоца у
jезикоцентричном схватању програмирања.

vii
viii

Такође, део књиге посвећен функционалном програмирању обимни-


jи jе од дела књиге посвећеног императивном програмирању. Разлог jе
прозаичан — концепти заjеднички за обе парадигме обрађени су с више
детаља у првом делу књиге. Из тога не треба извући закључак да jе функ-
ционална парадигма сложениjа или важниjа од императивне. Заправо, у
књизи се не даjе квалитативна предност ниjедноj парадигми.
Коначно, ова књига jе предвиђена да се користи као уџбеник на пред-
мету „Основи програмирања“, коjи се изводи на првоj години основ-
них академских студиjа програма „Информатика и рачунарство“ на
Криминалистичко-полициjском универзитету у Београду. Али веруjем да
може бити од интереса и ширем кругу читалаца.

.
ић
ов

а.
ат

ан
Гњ

ж
др
ан

за
ил

су
М

а
1.

ав
02

пр
–2

а
20

Св
20

а.
©

иj
рз
ве
д на
Ра
Садржаj

.
ић
Предговор аутора . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . vii
ов

а.
Листа слика . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xiii
ат

ан
Гњ

Листа табела . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xxvii

ж
др
Део I Концепти функционалног програмирања
ан

за
ил

1 Атомски типови података . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3


су

1.1 Увод . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
М

1.2 Аритметички изрази и префиксна нотациjа . . . . . . . . . . . . . . 3


а
1.

ав

1.3 Броjеви и изабране аритметичке операциjе . . . . . . . . . . . . . . . 8


02

1.4 Буловске вредности и функциjе . . . . . . . . . . . . . . . . . . . . . . . . . 16


пр

1.4.1 Предикати . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
–2

1.5 Стрингови . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
а
20

Св

1.5.1 Експлицитна конверзиjа између броjева и стрингова 25


20

1.6 Поређење вредности различитих типова података . . . . . . . . 27


а.

1.7 Закључне напомене . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28


©

иj

1.8 Задаци . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
рз

2 Основни инструменти апстракциjе у програмирању . . . . 31


ве

2.1 Глобалне променљиве . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31


2.2 Дефинисање функциjа . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
на

2.3 Условно извршавање . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40


д

2.3.1 Вишеструко гранање тока извршавања програма . . . 47


Ра

2.4 Функциjе вишег реда и безимене функциjе . . . . . . . . . . . . . . . 53


2.5 Локалне променљиве и лексички опсези . . . . . . . . . . . . . . . . . 57
2.5.1 Локално повезивање . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60
2.6 Подразумеване вредности улазних аргумената . . . . . . . . . . . 65
2.6.1 Именовани улазни аргументи . . . . . . . . . . . . . . . . . . . . . 66
2.7 Закључне напомене . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67

ix
x Садржаj

2.8 Задаци . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69

3 Рекурзивне функциjе . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
3.1 Увод . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
3.2 Рекурзивно издваjање цифара из целих броjева . . . . . . . . . . 72
3.2.1 Збир цифара ненегативног броjа . . . . . . . . . . . . . . . . . . 72
3.2.2 Броj цифара ненегативног целог броjа . . . . . . . . . . . . . 79
3.2.3 Производ цифара ненегативног целог броjа . . . . . . . . 79
3.2.4 Обртање редоследа цифара у ненегативном броjу . . 83
3.2.5 Проналажење цифре у ненегативном целом броjу . . 84
3.3 Рекурзивна обрада монотоних секвенци броjева . . . . . . . . . . 85
3.3.1 Факториjел ненегативног целог броjа . . . . . . . . . . . . . . 86
3.3.2 Фибоначиjев низ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
3.3.3 Прости броjеви . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93
.
ић
3.3.4 Наjмањи делилац . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97
3.4 Закључне напомене . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98
ов

а.
3.5 Задаци . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99
ат

ан
Рекурзивне структуре података . . . . . . . . . . . . . . . . . . . . . . . . . 101
Гњ

ж
4.1 Увод . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101

др
4.2 Листа као рекурзивна структура података . . . . . . . . . . . . . . . 101
ан

4.3 Однос између уређених парова и листи . . . . . . . . . . . . . . . . . .


за 105
ил

4.4 Изабране основне функциjе над листама . . . . . . . . . . . . . . . . . 107


су

4.4.1 Спаjање листи . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108


М

4.4.2 Броj елемената у листи . . . . . . . . . . . . . . . . . . . . . . . . . . 108


а
1.

ав

4.4.3 Читање елемената листе на основу индекса . . . . . . . . 112


02

4.4.4 Префикс листе . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113


пр

4.4.5 Суфикс листе . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117


–2

4.4.6 Обртање редоследа елемената у листи . . . . . . . . . . . . . 119


а
20

Св

4.4.7 Збир броjева у листи . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123


20

4.5 Изабране функциjе вишег реда над листама . . . . . . . . . . . . . 125


а.

4.5.1 Пресликавање листи . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 127


©

иj

4.5.2 Филтрирање листе . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 130


рз

4.5.3 Уређивање листе по задатом критериjуму . . . . . . . . . 131


4.6 Функциjе с произвољним броjем улазних аргумената . . . . . 134
ве

4.7 Закључне напомене . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137


на

4.8 Задаци . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138


д

Део II Концепти императивног програмирања


Ра

5 Типови података и инструменти апстракциjе у


императивноj парадигми . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143
5.1 Увод . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143
5.2 Атомски типови података . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144
5.2.1 Основне операциjе над константама . . . . . . . . . . . . . . . 145
Садржаj xi

5.3 Променљиве . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 148


5.3.1 Конвертовање типова атомских података . . . . . . . . . . 151
5.4 Функциjе и условно извршавање . . . . . . . . . . . . . . . . . . . . . . . . 154
5.5 Низови . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 159
5.5.1 Стрингови . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 162
5.6 Показивачи . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 164
5.7 Веза између низова и показивача . . . . . . . . . . . . . . . . . . . . . . . 165
5.8 Пренос улазних аргумената по вредности . . . . . . . . . . . . . . . . 171
5.9 Закључне напомене . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 172
5.10 Задаци . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 174

6 Итеративни процеси у императивном програмирању . . . 175


6.1 Увод . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 175
6.2 Итеративно издваjање цифара из целих броjева . . . . . . . . . . 175
.
ић
6.3 Итеративна обрада монотоних секвенци броjева . . . . . . . . . . 181
6.4 Итеративна обрада низова целих броjева . . . . . . . . . . . . . . . . 187
ов

а.
6.5 Итеративна обрада матрица целих броjева . . . . . . . . . . . . . . . 196
ат

ан
6.6 Итеративна обрада стрингова . . . . . . . . . . . . . . . . . . . . . . . . . . . 200
Гњ

6.7 Закључне напомене . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 204

ж
6.8 Задаци . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 205

др
ан

за
Библиографиjа . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 207
ил

су

Индекс поjмова . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 209


М

а
1.

ав
02

пр
–2

а
20

Св
20

а.
©

иj
рз
ве
д на
Ра
©
20
20
–2
02
Ра 1.
д М
на ил
ве ан
рз Гњ
иj ат
а.
Св ов
а ић
.
пр
ав
а
су
за
др
ж
ан
а.
Листа слика

.
ић
1.1 Резултат израчунавања израза (1.7). . . . . . . . . . . . . . . . . . . . . . 5
ов

а.
1.2 Резултат израчунавања израза (1.8). . . . . . . . . . . . . . . . . . . . . . 5
ат

ан
1.3 Приказ израчунавања израза (1.8) по корацима. . . . . . . . . . . 5
Гњ

ж
1.4 Хиjерархиjски приказ израчунавања израза (1.8). . . . . . . . . . 5

др
1.5 Резултат израчунавања израза (1.9). . . . . . . . . . . . . . . . . . . . . . 6
ан

1.6 Хиjерархиjски приказ израчунавања израза (1.9). . . . . . . . . . за 6


1.7 Резултати израчунавања израза (1.11) и (1.12). . . . . . . . . . . . . 7
ил

1.8 Резултати израчунавања израза (1.13) и (1.14). . . . . . . . . . . . . 7


су
М

1.9 Читљивиjи запис израза (1.15). . . . . . . . . . . . . . . . . . . . . . . . . . . 8


а

1.10 Примери основних аритметичких операциjа над


1.

ав

комплексним броjевима. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
02

пр

1.11 Илустрациjа зависности резултата примене аритметичких


–2

оператора +, −, ∗ и / од врсте операнада. . . . . . . . . . . . . . . . . 10


а

1.12 Свођење резултата израчунавања аритметичког израза


20

Св

(1.17), уз очување прецизности. . . . . . . . . . . . . . . . . . . . . . . . . . . 10


20

1.13 Непрецизно свођење резултата израчунавања


а.
©

аритметичког израза (1.18). . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11


иj

1.14 Пример непрецизног одузимања броjева. . . . . . . . . . . . . . . . . . 11


рз

1.15 Илустрациjа зависности резултата дељења нулом од


ве

дељеника. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
1.16 Илустрациjа функциjе quotient. . . . . . . . . . . . . . . . . . . . . . . . . . . 13
на

1.17 Илустрациjа функциjе remainder. . . . . . . . . . . . . . . . . . . . . . . . . 14


1.18 Илустрациjа издваjања цифара из целог броjа. . . . . . . . . . . . . 14
д
Ра

1.19 Илустрациjа функциjе numerator. . . . . . . . . . . . . . . . . . . . . . . . . 14


1.20 Илустрациjа функциjе denominator. . . . . . . . . . . . . . . . . . . . . . . 15
1.21 Илустрациjа функциja truncate, floor , ceiling и round. . . . . . 15
1.22 Илустрациjа функциja real−part, imag−part, expt и sqrt. . . 16
1.23 Илустрациjа операциjа релациjе. . . . . . . . . . . . . . . . . . . . . . . . . . 18
1.24 Илустрациjа буловских функциjа: конjункциjа,
дисjункциjа и негациjа. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19

xiii
xiv ЛИСТА СЛИКА

1.25 Резултат израчунавања израза (1.20). . . . . . . . . . . . . . . . . . . . . 19


1.26 Приказ израчунавања израза (1.20) по корацима. . . . . . . . . . 19
1.27 Хиjерархиjски приказ израчунавања израза (1.20). . . . . . . . . 19
1.28 Илустрациjа функциjе boolean=?. . . . . . . . . . . . . . . . . . . . . . . . . 20
1.29 Илустрациjа функциjе rational ?. . . . . . . . . . . . . . . . . . . . . . . . . . 21
1.30 Илустрациjа функциjе boolean?. . . . . . . . . . . . . . . . . . . . . . . . . . 21
1.31 Илустрациjа исписивања стрингова са специjалним
симболима. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
1.32 Индекси симбола у стринговима. . . . . . . . . . . . . . . . . . . . . . . . . . 23
1.33 Илустрациjа функциjе string−length. . . . . . . . . . . . . . . . . . . . . . 24
1.34 Илустрациjа функциjе string−append. . . . . . . . . . . . . . . . . . . . . 24
1.35 Илустрациjа функциjе substring. . . . . . . . . . . . . . . . . . . . . . . . . . 25
1.36 Илустрациjа операциjа релациjе између стрингова. . . . . . . . . 26
1.37 Илустрациjа функциjе string?. . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
.
ић
1.38 Илустрациjа функциjа number−>string и string−>number. . 27
1.39 Илустрациjа функциjе equal?. . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
ов

а.
1.40 Разлика између повратних вредности функциjа equal? и =
ат

ан
кад им се саопште улазни аргументи истих вредности, али
Гњ

ж
различитих прецизности. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28

др
2.1 Илустрациjа коришћења променљиве. . . . . . . . . . . . . . . . . . . . . 32
ан

за
2.2 Илустрациjа дефинисања глобалних променљивих. . . . . . . . . 32
ил

2.3 Индиковање грешке изазване референцирањем


су
М

недефинисане променљиве. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
2.4 Функциjа коjа прихвата броj x као улазни аргумент, и
а
1.

ав

израчунава вредност x2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
02

2.5 Синтаксичка структура дефинициjе функциjе дате на сл.


пр
–2

2.4. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
а

2.6 Резултати позивања функциjе дефинисане на сл. 2.4 кад


20

Св

jоj се саопште изабрани улазни аргументи. . . . . . . . . . . . . . . . . 34


20

2.7 Дефинициja функциje f (x) = 5x2 + 2x + 1. . . . . . . . . . . . . . . . . . 35


а.
©

2.8 Илустрациjа извршавања функциjе дефинисане на сл. 2.7. . 35


иj

2.9 Дефинициja функциje коjа израчунава запремину коцке. . . . 36


рз

2.10 Илустрациjа извршавања функциjе дефинисане на сл. 2.9. . 36


2.11 Дефинициja функциje коjа проверава дељивост jедног
ве

целог броjа другим целим броjем. . . . . . . . . . . . . . . . . . . . . . . . . 37


на

2.12 Илустрациjа извршавања функциjе дефинисане на сл. 2.11. 37


2.13 Дефинициja функциje коjа проверава да ли jе година
д
Ра

преступна. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
2.14 Друга дефинициja функциje коjа проверава да ли jе
година преступна. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
2.15 Трећа дефинициja функциje коjа проверава да ли jе
година преступна. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
2.16 Илустрациjа извршавања функциjа дефинисаних на сл.
2.13, 2.14 и 2.15. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
ЛИСТА СЛИКА xv

2.17 Дефинициja функциje коjа прихвата два реална броjа, и


као резултат враћа већи од њих. . . . . . . . . . . . . . . . . . . . . . . . . . 41
2.18 Илустрациjа извршавања функциjе дефинисане на сл. 2.17. 41
2.19 Приказ извршавања функциjе дефинисане на сл. 2.17 кад
jоj се саопште изабрани улазни аргументи. . . . . . . . . . . . . . . . . 42
2.20 Дефинициja функциje коjа прихвата два комплексна
броjа, и као резултат враћа „већи” од њих. . . . . . . . . . . . . . . . . 42
2.21 Илустрациjа извршавања функциjе дефинисане на сл. 2.20. 43
2.22 Приказ извршавања функциjе дефинисане на сл. 2.20 кад
jоj се саопште изабрани улазни аргументи. . . . . . . . . . . . . . . . . 43
2.23 Дефинициja функциje коjа прихвата три реална броjа, и
као резултат враћа наjвећи од њих. . . . . . . . . . . . . . . . . . . . . . . 44
2.24 Илустрациjа извршавања функциja дефинисаних на сл.
2.23 и 2.26. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
.
ић
2.25 Приказ извршавања функциjе дефинисане на сл. 2.23 кад
jоj се саопште изабрани улазни аргументи. . . . . . . . . . . . . . . . . 45
ов

а.
2.26 Друга дефинициja функциje коjа прихвата три реална
ат

ан
броjа, и као резултат враћа наjвећи од њих. . . . . . . . . . . . . . . . 45
Гњ

ж
2.27 Приказ извршавања функциjе дефинисане на сл. 2.26 кад

др
jоj се саопште изабрани улазни аргументи. . . . . . . . . . . . . . . . . 46
ан

2.28 Друга дефинициja функциje коjа проверава дељивост за


jедног целог броjа другим целим броjем. . . . . . . . . . . . . . . . . . . 46
ил

2.29 Друга дефинициja функциje коjа израчунава запремину


су
М

коцке. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
а

2.30 Илустрациjа извршавања функциjе дефинисане на сл. 2.29. 47


1.

ав

2.31 Синтаксичка структура угнежђеног израза за условно


02

пр

извршавање. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
–2

2.32 Синтаксичка структура израза за вишеструко гранање


а

тока извршавања програма коjи представља исти поступак


20

Св

израчунавања као израз 2.31. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48


20

2.33 Трећа дефинициja функциje коjа израчунава запремину


а.
©

коцке. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
иj

2.34 Синтаксичка структура израза за условно извршавање, у


рз

општем случаjу. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
ве

2.35 Дефинициjа функциjе коjа прихвата jедан аргумент, и


враћа стринг чиjи садржаj индикуjе скуп броjева коjем
на

припада улазни аргумент. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49


2.36 Илустрациjа извршавања функциjе дефинисане на сл. 2.35. 50
д
Ра

2.37 Илустрациjа неадекватног редоследа навођења логичких


услова у изразу за вишеструко гранање тока извршавања
програма. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
2.38 Илустрациjа извршавања функциjе дефинисане на сл. 2.37. 51
2.39 Дефинициja функциje sgn. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
2.40 Друга дефинициja функциje sgn. . . . . . . . . . . . . . . . . . . . . . . . . . 51
2.41 Дефинициja функциje (2.21). . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
xvi ЛИСТА СЛИКА

2.42 Друга дефинициja функциje (2.21). . . . . . . . . . . . . . . . . . . . . . . 52


2.43 Приказ извршавања функциjе дефинисане на сл. 2.42 кад
jоj се саопштe изабрани улазни аргументи. . . . . . . . . . . . . . . . . 52
2.44 Пример функциjе коjа прихвата друге функциjе као
улазне аргументе. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
2.45 Илустрациjа извршавања функциjе дефинисане на сл. 2.44. 54
2.46 Пример функциjе коjа као резултат враћа другу функциjу. 55
2.47 Илустрациjа извршавања функциjе дефинисане на сл. 2.46. 55
2.48 Безимена функциjа коjа прихвата броj x као улазни
аргумент, и израчунава вредност x2 . . . . . . . . . . . . . . . . . . . . . . . 56
2.49 Синтаксичка структура дефинициjе функциjе дате на сл.
2.48. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
2.50 Позивање безимене функциjе. . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
2.51 Пример дефинисања функциjе додељивањем имена
.
ић
безименоj функциjи. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
2.52 Безимена функциjа коjа прихвата два реална броjа, и као
ов

а.
резултат враћа већи од њих. Функциjа f дефинисана jе на
ат

ан
сл. 2.46. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
Гњ

ж
2.53 Саопштавање безимене функциjе као улазног аргумента. . . 57

др
2.54 Лексички опсег улазног аргумента. . . . . . . . . . . . . . . . . . . . . . . 58
ан

2.55 Идентична имена глобалних и локалних променљивих. . . . . за 58


2.56 Идентична имена улазних аргумената различитих функциjа. 59
ил

2.57 Истоимене променљиве и лексички опсези. . . . . . . . . . . . . . . . 59


су
М

2.58 Приказ израчунавања програма датог на сл. 2.57. . . . . . . . . . 60


а

2.59 Синтаксичка структура израза за паралелно локално


1.

ав

повезивање. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60
02

пр

2.60 Примери паралелног локалног повезивања. . . . . . . . . . . . . . . . 61


–2

2.61 Дефинициjа функциjе (2.30), са локалним променљивама. . 62


а

2.62 Дефинициjа функциjе (2.30), без увођења локалних


20

Св

променљивих. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
20

2.63 Ефикасниjа дефинициjа функциjе претходно приказане на


а.
©

сл. 2.44. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
иj

2.64 Синтаксичка структура израза за секвенциjално локално


рз

повезивање. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
ве

2.65 Дефинициjа сигмоидне функциjе. . . . . . . . . . . . . . . . . . . . . . . . . 63


2.66 Угнежђивање израза за локално повезивање. . . . . . . . . . . . . . 64
на

2.67 Пример поређења резултата непрецизног одузимања броjева. 65


2.68 Функциjа коjа пореди непрецизне броjеве. . . . . . . . . . . . . . . . . 66
д
Ра

2.69 Илустрациjа позивања функциjе дефинисане на сл. 2.68. . . . 66


2.70 Пример функциjе коjа прихвата два именована улазна
аргумента с подразумеваним вредностима. . . . . . . . . . . . . . . . . 67
2.71 Илустрациjа саопштавања улазних аргумената функциjи
дефинисаноj на сл. 2.70. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
2.72 Програм коjи илуструjе функционалност позивног стека. . . 68
2.73 Поступак извршавања програма датог на сл. 2.72. . . . . . . . . . 68
ЛИСТА СЛИКА xvii

2.74 Илустрациjа стања позивног стека за време извршавања


програма датог на сл. 2.72. Елементи у позивном стеку
представљаjу оквире стека коjи одговараjу позивима
функциjа. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68
2.75 Дефинициja функциje уз задатак 2.1. . . . . . . . . . . . . . . . . . . . . 69
2.76 Дефинициja функциje уз задатак 2.3. . . . . . . . . . . . . . . . . . . . . 70
2.77 Израз уз задатак 2.4. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70

3.1 Рекурзивна функциjа коjа за дати ненегативни цели броj


израчунава збир његових цифара. . . . . . . . . . . . . . . . . . . . . . . . . 74
3.2 Резултат позивања функциjе дефинисане на сл. 3.1 кад jоj
се саопшти улазни аргумент n = 1234. . . . . . . . . . . . . . . . . . . . . 74
3.3 Приказ рекурзивног извршавања функциjе дефинисане на
сл. 3.1 кад jоj се саопшти улазни аргумент n = 1234. . . . . . . . 74
.
ић
3.4 Илустрациjа стања позивног стека за време рекурзивног
извршавања функциjе дефинисане на сл. 3.1 кад jоj се
ов

а.
саопшти улазни аргумент n = 1234. . . . . . . . . . . . . . . . . . . . . . . . 75
ат

ан
3.5 Репно-рекурзивна функциjа коjа за дати ненегативни цели
Гњ

броj израчунава збир његових цифара. . . . . . . . . . . . . . . . . . . . 77

ж
3.6 Резултат позивања функциjе дефинисане на сл. 3.5 кад jоj

др
се саопшти улазни аргумент n = 1234. . . . . . . . . . . . . . . . . . . . . 78
ан

за
3.7 Приказ итеративног извршавања функциjе дефинисане на
ил

сл. 3.5 кад jоj се саопшти улазни аргумент n = 1234. . . . . . . . 78


су
М

3.8 Илустрациjа стања позивног стека за време итеративног


извршавања функциjе дефинисане на сл. 3.5 кад jоj се
а
1.

ав

саопшти улазни аргумент n = 1234. . . . . . . . . . . . . . . . . . . . . . . . 78


02

3.9 Рекурзивна функциjа коjа за дати ненегативни цели броj


пр
–2

израчунава броj његових цифара. . . . . . . . . . . . . . . . . . . . . . . . . 79


а

3.10 Репно-рекурзивна функциjа коjа за дати ненегативни цели


20

Св

броj израчунава броj његових цифара. . . . . . . . . . . . . . . . . . . . . 79


20

3.11 Неоптимизована рекурзивна функциjа коjа за дати


а.
©

ненегативни цели броj израчунава производ његових


иj

цифара. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80
рз

3.12 Неоптимизована репно-рекурзивна функциjа коjа за дати


ненегативни цели броj израчунава производ његових
ве

цифара. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80
на

3.13 Оптимизована рекурзивна функциjа коjа за дати


ненегативни цели броj израчунава производ његових
д
Ра

цифара. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
3.14 Оптимизована репно-рекурзивна функциjа коjа за дати
ненегативни цели броj израчунава производ његових
цифара. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
3.15 Резултат позивања функциja дефинисаних на сл. 3.11,
3.12, 3.13 и 3.14 кад им се саопште улазни аргументи
n1 = 1234 и n2 = 1204. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
xviii ЛИСТА СЛИКА

3.16 Приказ извршавања функциjа дефинисаних на сл. 3.11,


3.12, 3.13 и 3.14 кад им се саопшти улазни аргумент
n1 = 1234. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82
3.17 Приказ извршавања функциjа дефинисаних на сл. 3.11,
3.12, 3.13 и 3.14 кад им се саопшти улазни аргумент
n2 = 1204. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
3.18 Репно-рекурзивна функциjа коjа генерише броj коjи се
добиjе кад се цифре улазног ненегативног целог броjа
напишу у обрнутом редоследу. . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
3.19 Резултати позивања функциjе дефинисане на сл. 3.18 кад
jоj се саопштe изабрани улазни аргументи. . . . . . . . . . . . . . . . . 84
3.20 Репно-рекурзивна функциjа коjа проверава да ли
ненегативни цели броj n садржи цифру c. . . . . . . . . . . . . . . . . . 85
3.21 Резултати позивања функциjе дефинисане на сл. 3.20 за
.
ић
изабране улазне аргументе. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85
3.22 Рекурзивна функциjа коjа израчунава факториjел датог
ов

а.
ненегативног целог броjа n. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86
ат

ан
3.23 Репно-рекурзивна функциjа коjа израчунава факториjел
Гњ

ж
датог ненегативног целог броjа n. . . . . . . . . . . . . . . . . . . . . . . . . 87

др
3.24 Рекурзивна функциjа коjа израчунава n-ти елемент
ан

Фибоначиjевог низа. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
за 88
3.25 Резултат позивања функциjе дефинисане на сл. 3.24 кад
ил

jоj се саопшти улазни аргумент n = 6. . . . . . . . . . . . . . . . . . . . . 88


су
М

3.26 Приказ рекурзивног извршавања функциjе дефинисане на


а

сл. 3.24 кад jоj се саопшти улазни аргумент n = 6. . . . . . . . . . 89


1.

ав

3.27 Хиjерархиjа рекурзивних позива приликом рекурзивног


02

пр

извршавања функциjе дефинисане на сл. 3.24 кад jоj се


–2

саопшти улазни аргумент n = 6. . . . . . . . . . . . . . . . . . . . . . . . . . . 89


а

3.28 Приордер-обилазак хиjерархиjе рекурзивних позива


20

Св

приликом рекурзивног извршавања функциjе дефинисане


20

на сл. 3.24 кад jоj се саопшти улазни аргумент n = 6. . . . . . . 90


а.
©

3.29 Илустрациjа стања позивног стека за време рекурзивног


иj

извршавања функциjе дефинисане на сл. 3.24 кад jоj се


рз

саопшти улазни аргумент n = 6. . . . . . . . . . . . . . . . . . . . . . . . . . . 91


ве

3.30 Експоненциjални раст броja рекурзивних позива функциjе


дефинисане на сл. 3.24 у односу на вредност улазног
на

аргумента. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92
3.31 Репно-рекурзивна функциjа коjа израчунава n-ти елемент
д
Ра

Фибоначиjевог низа. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93
3.32 Резултат позивања функциjе дефинисане на сл. 3.31 кад
jоj се саопшти улазни аргумент n = 6. . . . . . . . . . . . . . . . . . . . . 93
3.33 Приказ итеративног извршавања функциjе дефинисане на
сл. 3.31 кад jоj се саопшти улазни аргумент n = 6. . . . . . . . . . 93
3.34 Репно-рекурзивна функциjа коjа проверава да ли jе
природни броj n прост. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94
ЛИСТА СЛИКА xix

3.35 Резултати позивања функциjе дефинисане на сл. 3.34 кад


jоj се саопште изабрани улазни аргументи. . . . . . . . . . . . . . . . . 95
3.36 Приказ итеративног извршавања функциjе дефинисане на
сл. 3.34 кад jоj се саопште изабрани улазни аргументи. . . . . 95
3.37 Прва верзиjа оптимизоване функциjе коjа проверава да ли
jе природни броj n прост. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96
3.38 Приказ итеративног извршавања функциjа дефинисаних
на сл. 3.37 и 3.39 кад им се саопште изабрани улазни
аргументи. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96
3.39 Друга верзиjа оптимизоване функциjе коjа проверава да
ли jе природни броj n прост. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97
3.40 Репно-рекурзивна функциjа коjа одређуjе наjмањи прости
делилац природног броjа n, већег од 1. . . . . . . . . . . . . . . . . . . . 98
3.41 Приказ итеративног извршавања функциjе дефинисане на
.
ић
сл. 3.40 кад jоj се саопште изабрани улазни аргументи. . . . . 98
ов

а.
4.1 Интерно представљање уређеног пара у рачунарскоj
ат

ан
мемориjи. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102
Гњ

4.2 Дефинисање уређеног пара (1, 2). . . . . . . . . . . . . . . . . . . . . . . . . 102

ж
4.3 Интерно представљање уређеног пара коjи садржи само

др
први елемент, док jе други елемент недефинисан. . . . . . . . . . 102
ан

за
4.4 Конструисање уређеног пара у коjем jе само први елемент
ил

дефинисан. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103
су
М

4.5 Интерно представљање листе као секвенце рекурзивно


угнежђених парова. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103
а
1.

ав

4.6 Дефинисање листе броjева ’(1 2 3 4) као секвенце


02

рекурзивно угнежђених парова. . . . . . . . . . . . . . . . . . . . . . . . . . . 104


пр
–2

4.7 Дефинисање листе броjева ’(1 2 3 4) позивањем функциjе


а

list. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104
20

Св

4.8 Интерно представљање листе ’(1 2 3 4). . . . . . . . . . . . . . . . . . . 104


20

4.9 Дефинисање листе броjева ’((1 "a") (2) #t) позивањем


а.
©

функциjе list. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105


иj

4.10 Интерно представљање листе ’((1 "a") (2) #t). . . . . . . . . . . . 105


рз

4.11 Издваjање елемената из уређеног пара. . . . . . . . . . . . . . . . . . . . 106


4.12 Издваjање елемената из непразне листе. . . . . . . . . . . . . . . . . . . 106
ве

4.13 Резултат извршавања функциjа car и cdr кад им се


на

саопшти листа коjа садржи jедан елемент. . . . . . . . . . . . . . . . . 106


4.14 Празна листа. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107
д
Ра

4.15 Резултати позивања функциjе append кад jоj се саопште


изабрани аргументи. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109
4.16 Резултати позивања функциjе length кад jоj се саопште
изабрани аргументи. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109
4.17 Рекурзивна функциjа коjа израчунава броj елемената у
листи. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110
xx ЛИСТА СЛИКА

4.18 Резултати позивања функциjе дефинисане на сл. 4.17 кад


jоj се саопште изабрани улазни аргументи. . . . . . . . . . . . . . . . . 110
4.19 Приказ рекурзивног извршавања функциjе дефинисане на
сл. 4.17 кад jоj се саопшти изабрани улазни аргумент. . . . . . 111
4.20 Репно-рекурзивна функциjа коjа израчунава броj
елемената у листи. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111
4.21 Приказ итеративног извршавања функциjе дефинисане на
сл. 4.20 кад jоj се саопшти изабрани улазни аргумент. . . . . . 111
4.22 Резултати позивања функциjе list-ref кад jоj се саопште
изабрани аргументи. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112
4.23 Репно-рекурзивна функциjа коjа враћа елемент листе l
коjем jе додељен индекс n. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113
4.24 Резултати позивања функциjе дефинисане на сл. 4.23 кад
jоj се саопште изабрани улазни аргументи. . . . . . . . . . . . . . . . . 113
.
ић
4.25 Приказ итеративног извршавања функциjе дефинисане на
сл. 4.23 кад jоj се саопшти изабрани улазни аргумент. . . . . . 113
ов

а.
4.26 Резултати позивања функциjе take кад jоj се саопште
ат

ан
изабрани аргументи. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114
Гњ

ж
4.27 Рекурзивна функциjа коjа прихвата листу l и ненегативни

др
цели броj k, и враћа нову листу коjа садржи првих n
ан

елемената листе k. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
за 115
4.28 Резултати позивања функциjе дефинисане на сл. 4.27 кад
ил

jоj се саопште изабрани улазни аргументи. . . . . . . . . . . . . . . . . 115


су
М

4.29 Приказ рекурзивног извршавања функциjе дефинисане на


а

сл. 4.27 кад jоj се саопшти изабрани улазни аргумент. . . . . . 115


1.

ав

4.30 Репно-рекурзивна функциjа коjа прихвата листу l и


02

пр

ненегативни цели броj k, и враћа нову листу коjа садржи


–2

првих n елемената листе k. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116


а

4.31 Приказ итеративног извршавања функциjе дефинисане на


20

Св

сл. 4.30 кад jоj се саопшти изабрани улазни аргумент. . . . . . 116


20

4.32 Упоредни приказ генерисања резултуjуће листе у


а.
©

рекурзивном процесу дефинисаном на сл. 4.27, и


иj

итеративном процесу дефинисаном на сл. 4.30, за изабране


рз

улазне аргументе. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117


ве

4.33 Резултати позивања функциjе drop кад jоj се саопште


изабрани аргументи. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117
на

4.34 Рекурзивна функциjа коjа прихвата листу l и ненегативни


цели броj k, и враћа листу коjа се добиjе кад се из улазне
д
Ра

листе уклони првих k елемената. . . . . . . . . . . . . . . . . . . . . . . . . . 118


4.35 Резултати позивања функциjе дефинисане на сл. 4.34 кад
jоj се саопште изабрани улазни аргументи. . . . . . . . . . . . . . . . . 118
4.36 Приказ итеративног извршавања функциjе дефинисане на
сл. 4.34 кад jоj се саопштe изабрани улазни аргументи. . . . . 119
4.37 Резултати позивања функциjе reverse кад jоj се саопште
изабрани аргументи. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 119
ЛИСТА СЛИКА xxi

4.38 Непотпуна рекурзивна функциjа коjа обрће редослед


елемената у листи. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 120
4.39 Резултати позивања функциjе дефинисане на сл. 4.38 кад
jоj се саопште изабрани улазни аргументи. . . . . . . . . . . . . . . . . 121
4.40 Приказ рекурзивног извршавања функциjе дефинисане на
сл. 4.38 кад jоj се саопшти изабрани улазни аргумент. . . . . . 121
4.41 Рекурзивна функциjа коjа обрће редослед елемената у
листи — и свим угнежђеним листама. . . . . . . . . . . . . . . . . . . . . 122
4.42 Резултати позивања функциjе дефинисане на сл. 4.41 кад
jоj се саопште изабрани улазни аргументи. . . . . . . . . . . . . . . . . 122
4.43 Приказ рекурзивног извршавања функциjе дефинисане на
сл. 4.41 кад jоj се саопшти изабрани улазни аргумент. . . . . . 123
4.44 Репно-рекурзивна функциjа коjа обрће редослед елемената
у листи — и свим угнежђеним листама. . . . . . . . . . . . . . . . . . . . 123
.
ић
4.45 Приказ итеративног извршавања функциjе дефинисане на
сл. 4.44 кад jоj се саопшти изабрани улазни аргумент. . . . . . 124
ов

а.
4.46 Рекурзивна функциjа коjа израчунава збир броjева
ат

ан
садржаних у листи. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125
Гњ

ж
4.47 Резултати позивања функциjе дефинисане на сл. 4.46 кад

др
jоj се саопште изабрани улазни аргументи. . . . . . . . . . . . . . . . . 125
ан

4.48 Приказ рекурзивног извршавања функциjе дефинисане на за


сл. 4.46 кад jоj се саопшти изабрани улазни аргумент. . . . . . 126
ил

4.49 Репно-рекурзивна функциjа коjа израчунава збир броjева


су
М

садржаних у листи. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126


а

4.50 Приказ итеративног извршавања функциjе дефинисане на


1.

ав

сл. 4.49 кад jоj се саопшти изабрани улазни аргумент. . . . . . 126


02

пр

4.51 Резултати позивања функциjе map кад jоj се саопште


–2

изабрани аргументи. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 127


а

4.52 Рекурзивна функциjа коjа прихвата функциjу


20

Св

p и листу l = ’(e0 e1 . . . en−1 ), и генерише листу


20

’(( f e0 ) ( f e1 ) . . . ( f en−1 )). . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 128


а.
©

4.53 Резултати позивања функциjе дефинисане на сл. 4.52 кад


иj

jоj се саопште изабрани улазни аргументи. . . . . . . . . . . . . . . . . 128


рз

4.54 Приказ рекурзивног извршавања функциjе дефинисане на


ве

сл. 4.52 кад jоj се саопште изабрани улазни аргументи. . . . . 129


4.55 Репно-рекурзивна функциjа коjа прихвата функциjу
на

p и листу l = ’(e0 e1 . . . en−1 ), и генерише листу


’(( f e0 ) ( f e1 ) . . . ( f en−1 )). . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 129
д
Ра

4.56 Приказ итеративног извршавања функциjе дефинисане на


сл. 4.55 кад jоj се саопште изабрани улазни аргументи. . . . . 130
4.57 Резултати позивања функциjе filter кад jоj се саопште
изабрани аргументи. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 130
xxii ЛИСТА СЛИКА

4.58 Функциjа коjа прихвата функциjу p и листу l, и генерише


листу коjа садржи оне елементе из листе l за коjе
функциjа p генерише вредност #t, у редоследу у ком су
наведени у улазноj листи. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131
4.59 Резултати позивања функциjе дефинисане на сл. 4.58 кад
jоj се саопште изабрани улазни аргументи. . . . . . . . . . . . . . . . . 131
4.60 Резултати позивања функциjе sort кад jоj се саопште
изабрани аргументи. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133
4.61 Функциjа коjа прихвата листу l и функциjу p, и генерише
нову листу коjа садржи елементе листе l уређене по
критериjуму коjи спецификуjе функциjа p. . . . . . . . . . . . . . . . 134
4.62 Резултати позивања функциjе дефинисане на сл. 4.61 кад
jоj се саопште изабрани улазни аргументи. . . . . . . . . . . . . . . . . 135
4.63 Илустрациjа извршавања функциjе дефинисане на сл.
.
ић
4.61, за позив: (uredi ’(22 19 109 56 47 17) <). . . . . . . . . . . . . . 135
4.64 Функциjа коjа прихвата произвољно дугачку секвенцу
ов

а.
аргумената произвољних типова података, и израчунава
ат

ан
збир свих броjева садржаних у њоj. . . . . . . . . . . . . . . . . . . . . . . 136
Гњ

ж
4.65 Резултати позивања функциjе дефинисане на сл. 4.64 кад

др
jоj се саопште изабрани улазни аргументи. . . . . . . . . . . . . . . . . 136
ан

4.66 Функциjа коjа прихвата произвољни низ броjева, и за


израчунава њихов збир. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137
ил

4.67 Резултати позивања функциjе дефинисане на сл. 4.66 кад


су
М

jоj се саопште изабрани улазни аргументи. . . . . . . . . . . . . . . . . 137


а
1.

ав

5.1 Илустрациjа зависности резултата примене оператора


02

сабирања од врсте броjева над коjима jе оператор примењен.146


пр
–2

5.2 Илустрациjа зависности резултата примене оператора


а

дељења од врсте броjева над коjима jе оператор примењен. 146


20

Св

5.3 Илустрациjа издваjања цифара из целог броjа у


20

програмском jезику Ц. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 146


а.
©

5.4 Илустрациjа примене релационих оператора у


иj

програмском jезику Ц. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147


рз

5.5 Илустрациjа примене буловских оператора у програмском


jезику Ц. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 148
ве

5.6 Интерна репрезентациjа декларисања и инициjализовања


на

променљивих. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149
5.7 Додељивање вредности променљивоj. . . . . . . . . . . . . . . . . . . . . 150
д
Ра

5.8 Илустрациjа десне асоциjативности оператора додељивања. 150


5.9 Илустрациjа примене оператора инкрементирања и
декрементирања. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 152
5.10 Пример некоректног израчунавања просечне вредности
два цела броjа. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153
5.11 Примери коректног израчунавања просечне вредности два
цела броjа. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153
ЛИСТА СЛИКА xxiii

5.12 Функциjа коjа прихвата реални броj x, и израчунава


вредност x2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 154
5.13 Синтаксичка структура дефинициjе функциjе дате на сл.
5.12. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 155
5.14 Синтаксичка структура наредбе условног извршавања. . . . . 155
5.15 Дефинициja функциje коjа прихвата два реална броjа, и
као резултат враћа већи од њих. . . . . . . . . . . . . . . . . . . . . . . . . . 155
5.16 Дефинициja функциje коjа прихвата три реална броjа, и
као резултат враћа наjвећи од њих. . . . . . . . . . . . . . . . . . . . . . . 156
5.17 Друга дефинициja функциje коjа прихвата три реална
броjа, и као резултат враћа наjвећи од њих. . . . . . . . . . . . . . . . 156
5.18 Дефинициja функциje коjа проверава дељивост jедног
целог броjа другим целим броjем. . . . . . . . . . . . . . . . . . . . . . . . . 157
5.19 Друга дефинициja функциje коjа проверава дељивост
.
ић
jедног целог броjа другим целим броjем. . . . . . . . . . . . . . . . . . . 158
5.20 Пример употребе оператора додељивања у буловском изразу.158
ов

а.
5.21 Декларисање низа и приступање његовим елементима. . . . . 159
ат

ан
5.22 Илустрациjа стања у мемориjи релевантних за примере
Гњ

ж
(а,б) 5.17 и (в) 5.18. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 160

др
5.23 Приступ елементима jеднодимензионалног низа. . . . . . . . . . . 160
ан

5.24 Приступ елементима дводимензионалног низа (тj., матрице).161 за


5.25 Приступ елементима тродимензионалног низа. . . . . . . . . . . . . 162
ил

5.26 Интерна репрезентациjа стринга. . . . . . . . . . . . . . . . . . . . . . . . . 163


су
М

5.27 Декларисање показивача и посредно приступање


а

променљивоj на коjу показуjе. . . . . . . . . . . . . . . . . . . . . . . . . . . . 165


1.

ав

5.28 Илустрациjа секвенце стања у мемориjи релевантних за


02

пр

ко̂д приказан на сл. 5.27. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 165


–2

5.29 Илустрациjа примене показивача. . . . . . . . . . . . . . . . . . . . . . . . . 166


а

5.30 Илустрациjа секвенце стања у мемориjи релевантних за


20

Св

ко̂д приказан на сл. 5.29. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 166


20

5.31 Илустрациjа концептуалне везе између низова и показивача.167


а.
©

5.32 Пример контекста у коjем jе могуће израчунати капацитет


иj

локално декларисаног низа. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 168


рз

5.33 Пример контекста у коjем ниjе могуће израчунати


ве

капацитет низа саопштеног функциjи. . . . . . . . . . . . . . . . . . . . . 169


5.34 Интерна репрезентациjа стринга и низа симбола. . . . . . . . . . . 170
на

5.35 Функциjа коjа враћа стринг чиjи садржаj представља


облик именице човек у номинативу коjи по броjу одговара
д
Ра

вредности улазног целоброjног аргумента. . . . . . . . . . . . . . . . . 171


5.36 Илустрациjа преноса улазних аргумената по вредности. . . . . 172
5.37 Илустрациjа стања позивног стека за време извршавања
функциjе f дефинисане на сл. 5.36: (a) приликом позивања
функциjе f1 , (б) након извршавања функциjе f1 , (в)
приликом позивања функциjе f2 , (г) након извршавања
функциjе f2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 173
xxiv ЛИСТА СЛИКА

6.1 Синтаксички запис петље. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 175


6.2 Функциjа коjа израчунава збир цифара датог ненегативнoг
целог броjа. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 176
6.3 Функциjа коjа израчунава броj цифара датог природног
броjа n. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 178
6.4 Функциjа коjа израчунава производ цифара датог
ненегативнoг целог броjа. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 178
6.5 Функциjа коjа генерише броj добиjен обртањем редоследа
цифара улазног ненегативног целог броjа. . . . . . . . . . . . . . . . . 180
6.6 Алтернативна синтаксичка структура петље. . . . . . . . . . . . . . 181
6.7 Синтаксичка структура еквивалентна, у општем случаjу,
синтаксичкоj структури приказаноj на сл. 6.6. . . . . . . . . . . . . 181
6.8 Функциja коjа израчунава факториjел датог ненегативног
целог броjа. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 182
.
ић
6.9 Друга функциja коjа израчунава факториjел датог
ненегативног целог броjа. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 183
ов

а.
6.10 Трећа функциja коjа израчунава факториjел датог
ат

ан
ненегативног целог броjа. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 184
Гњ

ж
6.11 Функциja коjа проверава да ли jе дати природни броj n

др
прост. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 185
ан

6.12 Функциja коjа израчунава n-ти елемент Фибоначиjевог низа.185 за


6.13 Функциjа коjа израчунава збир елемената низа реалних
ил

броjева. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 188
су
М

6.14 Функциjа коjа израчунава максимални броj непразног


а

низа целих броjева. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 189


1.

ав

6.15 Функциjа коjа израчунава броj jављања максималног


02

пр

броjа у непразном низу целих броjева. . . . . . . . . . . . . . . . . . . . . 190


–2

6.16 Друга функциjа коjа израчунава броj jављања


а

максималног броjа у непразном низу целих броjева. . . . . . . . 191


20

Св

6.17 Трећа функциjа, квадратне временске сложености, коjа


20

израчунава броj jављања максималног броjа у непразном


а.
©

низу целих броjева. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 191


иj

6.18 Функциjа коjа обрће редослед елемената у непразном низу


рз

реалних броjева. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 192


ве

6.19 Функциjа коjа проверава да ли jе непразни низ целих


броjева „палиндром“. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 193
на

6.20 Функциjа коjа израчунава броj различитих елемената у


датом непразном низу целих броjева. . . . . . . . . . . . . . . . . . . . . . 194
д
Ра

6.21 Функциjа коjа уређуjе дати низ целих броjева монотоно


неопадаjуће. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 196
6.22 Функциjа коjа израчунава збир парних елемената дате
матрице целих броjева. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 198
6.23 Друга функциjа коjа израчунава збир парних елемената
дате матрице целих броjева. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 198
ЛИСТА СЛИКА xxv

6.24 Функциjа коjа проверава да ли jе дата квадратна матрица


целих броjева симетрична у односу на главну диjагоналу. . . 200
6.25 Функциjа коjа одређуjе броj симбола у датом стрингу. . . . . . 202
6.26 Друга функциjа коjа одређуjе броj симбола у датом стрингу.202
6.27 Приказ итеративног извршавања функциjе дефинисане на
сл. 6.26 кад jоj се саопшти изабрани аргумент. . . . . . . . . . . . . 203
6.28 Функциjа коjа лексикографски пореди два стринга. . . . . . . . 203

.
ић
ов

а.
ат

ан
Гњ

ж
др
ан

за
ил

су
М

а
1.

ав
02

пр
–2

а
20

Св
20

а.
©

иj
рз
ве
д на
Ра
©
20
20
–2
02
Ра 1.
д М
на ил
ве ан
рз Гњ
иj ат
а.
Св ов
а ић
.
пр
ав
а
су
за
др
ж
ан
а.
Листа табела

.
ић
1.1 Примери елемената скупова броjева. . . . . . . . . . . . . . . . . . . . . . 9
ов

а.
1.2 Илустрациjа изабраних предиката коjи се односе на броjеве. 21
ат

ан
Гњ

3.1 Упоредни подаци о временскоj и просторноj ефикасности

ж
функциja дефинисаних на сл. 3.11, 3.12, 3.13 и 3.14 кад им

др
се саопште улазни аргументи n1 = 1234 и n2 = 1204. . . . . . . . . 82
ан

за
3.2 Броjеви рекурзивних позивања — c(n) — функциjе
ил

дефинисане на сл. 3.24 кад jоj се саопште улазни


су
М

аргументи n ∈ {1, 2, . . . , 40}. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91


а
1.

ав

4.1 Илустрациjа изабраних предиката коjи се односе на


02

уређене парове и листе. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108


пр
–2

5.1 Примери константи атомских типова података у


а
20

Св

програмском jезику Ц. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144


20

5.2 Оператори коjи извршаваjу основне операциjе над


а.

константама у програмском jезику Ц. Сви наведени


©

иj

оператори су бинарни, осим оператора негациjе (!), коjи jе


унаран. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 145
рз
ве

6.1 Приказ итеративног извршавања функциjе дефинисане на


сл. 6.2 кад jоj се саопшти изабрани аргумент. . . . . . . . . . . . . . 177
на

6.2 Приказ итеративног извршавања функциjе дефинисане на


д

сл. 6.4 кад jоj се саопшти изабрани аргумент. . . . . . . . . . . . . . 179


Ра

6.3 Приказ итеративног извршавања функциjе дефинисане на


сл. 6.5 кад jоj се саопшти изабрани аргумент. . . . . . . . . . . . . . 180
6.4 Приказ итеративног извршавања функциjе дефинисане на
сл. 6.8 кад jоj се саопшти изабрани аргумент. . . . . . . . . . . . . . 183
6.5 Приказ итеративног извршавања функциjе дефинисане на
сл. 6.12 кад jоj се саопшти изабрани аргумент. . . . . . . . . . . . . 186

xxvii
xxviii ЛИСТА ТАБЕЛА

6.6 Приказ итеративног извршавања функциjе дефинисане на


сл. 6.13 кад jоj се саопште изабрани аргументи. . . . . . . . . . . . 188
6.7 Приказ итеративног извршавања функциjе дефинисане на
сл. 6.14 кад jоj се саопште изабрани аргументи. . . . . . . . . . . . 189
6.8 Приказ итеративног извршавања функциjе дефинисане на
сл. 6.18 кад jоj се саопште изабрани аргументи. У свакоj
итерациjи, елемент a[i] означен jе сивом боjом, а елемент
a[n − 1 − i] црним оквиром. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 192
6.9 Приказ итеративног извршавања функциjе дефинисане на
сл. 6.20 кад jоj се саопште изабрани аргументи. У свакоj
итерациjи, елемент a[i] означен jе сивом боjом, а елемент
a[ j] црним оквиром. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 195
6.10 Приказ итеративног извршавања функциjе дефинисане на
сл. 6.21 кад jоj се саопште изабрани аргументи. У свакоj
.
ић
итерациjи, елемент a[i] означен jе сивом боjом, а елемент
a[ j] црним оквиром. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 197
ов

а.
6.11 Приказ итеративног извршавања функциjе дефинисане на
ат

ан
сл. 6.22 кад jоj се саопште изабрани аргументи. У свакоj
Гњ

ж
итерациjи, елемент a[i][ j] означен jе сивом боjом. . . . . . . . . . . 199

др
6.12 Приказ итеративног извршавања функциjе дефинисане на
ан

сл. 6.24 кад jоj се саопште изабрани аргументи. У свакоj за


итерациjи, елемент a[i][ j] означен jе сивом боjом, а елемент
ил

a[ j][i] црним оквиром. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 201


су
М

а
1.

ав
02

пр
–2

а
20

Св
20

а.
©

иj
рз
ве
д на
Ра
©
20
20
–2
02
Ра 1.
д М
на ил
ве ан
рз Гњ
иj ат
а.
Св ов
а ић
.
пр
ав
а
су
за
др
ж
ан
а.
програмирања
Концепти функционалног
Део I
©
20
20
–2
02
Ра 1.
д М
на ил
ве ан
рз Гњ
иj ат
а.
Св ов
а ић
.
пр
ав
а
су
за
др
ж
ан
а.
Поглавље 1
Атомски типови података

.
ић
1.1 Увод
ов

а.
ат

ан
Сви програми манипулишу подацима. Због тога су сви програмски
jезици дизаjнирани тако да омогућаваjу примену различитих типова по-
Гњ

ж
датака. Упркос разликама између програмских jезика, jедан од заjеднич-

др
ких дизаjнерских концепата jе да се типови података могу поделити у две
ан

широке категориjе:
за
ил

• атомске типовe података и,


су
М

• сложене типове података.


а
1.

ав

За тип података кажемо да jе атомски кад се у контексту датог про-


02

грамског jезика не може представити као композициjа других атомских


пр

типова података. У складу с тим, сложени типови података представљаjу


–2

композициjе атомских типова података.


а
20

Св

У овом поглављу, читалац се првo упознаjе с префиксном нотациjом


20

израза коjа jе карактеристична за синтаксу програмског jезика Ракет, и


а.

поступцима формирања и израчунавања аритметичких израза. Потом су


©

иj

представљена три изабрана атомска типа података у програмском jезику


Ракет — броjеви, буловске вредности и симболички подаци (тj., стринго-
рз

ви) — и операциjе над њима.


ве
д на

1.2 Аритметички изрази и префиксна нотациjа


Ра

У математици, аритметички изрази уобичаjено се представљаjу у тзв.


инфиксноj нотациjи, коjа подразумева да се аритметички оператори на-
воде између операнада. Нпр., у инфиксно записаном аритметичком из-
разу сабирања два броjа:
1+2 , (1.1)

3
4 1 Атомски типови података

оператор + наведен jе између вредности 1 и 2. Синтакса програмског


jезика Ракет заснована jе на тзв. префиксноj нотациjи, коjа подразумева
следеће:
• оператори се наводе испред операнада,
• изрази се наводе у облим заградама.
Израз (1.1) у префиксноj нотациjи гласи:

(+ 1 2) . (1.2)

Слично, операциjе одузимања, множења и дељења два броjа могу се пред-


ставити на следећи начин:

(− 1 2), (∗ 1 2), (/ 1 2) . (1.3)


.
ић
Пример 1.1. Преведимо следећи израз у префиксни запис:
ов

а.
2 · (7 + 3) − 4 . (1.4)
ат

ан
Гњ

Размотримо редослед извршавања операциjа у изразу (1.4):

ж
др
• због заграда, прво се извршава операциjа сабирања, (7 + 3) = 10,
ан

• потом операциjа множења, 2 · 10 = 20, jер jе множење приоритетниjе у


за
односу на одузимање,
ил

су

• и, коначно, операциjа одузимања, 20 − 4 = 16.


М

Истим редоследом ћемо формирати префиксни запис:


а
1.

ав

• прво се извршава сабирање 7 + 3, тj.,


02

пр
–2

(+ 7 3) , (1.5)
а
20

Св

• потом се збир множи с 2, тj.,


20

а.

(∗ 2 (+ 7 3)) , (1.6)
©

иj

• и, на краjу, од производa се одузме 4, тj.,


рз
ве

(− (∗ 2 (+ 7 3)) 4) . (1.7)
на

Префиксни израз (1.7) одговара инфиксном изразу (1.4). Кад се израз


д

(1.7) саопшти интерпретатору, резултат израчунавања jеднак je 16 (в.


Ра

сл. 1.1).
Пример 1.2. Израчунаjмо вредност следећег израза:

(/ (∗ 4 (+ 3 6)) 3) . (1.8)

Кад се израз (1.8) саопшти интерпретатору, резултат израчунавања


jеднак jе 12 (в. сл. 1.2). Израчунавање овог израза по корацима приказано
1.2 Аритметички изрази и префиксна нотациjа 5
 
> (− ( ∗ 2 (+ 7 3 ) ) 4 )
16
 

Слика 1.1 Резултат израчунавања израза (1.7).

jе на сл. 1.3. У сваком кораку израчунаваjу се „наjугнежђениjи“ делови


израза, чиме се запис израза постепено упрошћава, све док се не сведе
на коначну вредност. Хиjерархиjски приказ израчунавања израза (1.8)
дат jе на сл. 1.4. Кажемо да се израчунавање врши одоздо-нагоре, тj.,
од терминалних чворова ка корену стабла, што jе наглашено усмереним
гранама у стаблу.

 . 
ић
> ( / ( ∗ 4 (+ 3 6 ) ) 3 )
ов
12

а.
 
ат

ан
Гњ

Слика 1.2 Резултат израчунавања израза (1.8).

ж
др
ан

за
ил

су
( / ( ∗ 4 (+ 3 6 ) ) 3 )
М

( / (∗ 4 9) 3)
( / 36 3 )
а
1.

ав

12
02

пр
–2

Слика 1.3 Приказ израчунавања израза (1.8) по корацима.


а
20

Св
20

а.
©

12
иj
рз

/ 36 3
ве
на

∗ 4 9
Слика 1.4 Хиjерархиjски
д
Ра

приказ израчунавања
израза (1.8). + 3 6

Пример 1.3. Посматраjмо следећи израз:

(− (+ 4 3) (+ 2 1)) . (1.9)
6 1 Атомски типови података

Кад се оваj израз саопшти интерпретатору, резултат израчунавања jед-


нак jе 4 (в. сл. 1.5), a хиjерархиjски приказ израчунавања израза дат jе на
сл. 1.6. Слично као у примеру 1.2, израчунавање се врши одоздо-нагоре,
тj., од терминалних чворова ка корену стабла. За разлику од претход-
ног примера, овде се jавља и додатно питање: да ли се делови израза
коjи се налазе на истом хиjерархиjском нивоу израчунаваjу у редоследу
слева-надесно или у редоследу сдесна-налево? Кад би редослед израчу-
навања био слева-надесно, то би значило да се прво израчунава део из-
раза (+ 4 3), а после део израза (+ 2 1). У супротном, кад би редослед
израчунавања био сдесна-налево, део израза (+ 2 1) би се израчунавао
пре дела израза (+ 4 3). У овом примеру, резултат израчунавања израза
(1.9) исти jе, без обзира на усвоjени редослед. Међутим, у општем случа-
jу, важно jе приметити да jе одговор на ово питање одређен дизаjном и
имплементациjом конкретног програмског преводиоца или интерпрета-
.
ић
тора, чиjи детаљи нису обавезно унапред познати аутору програма. Због
тога, добра пракса програмирања подразумева да се не пишу програми
ов

а.
чиjи резултат извршавања зависи од претпоставке1 одређеног редоследа
ат

ан
израчунавања делова израза на истом хиjерархиjском нивоу.
Гњ

ж
 

др
ан

> (− (+ 4 3 ) (+ 2 1 ) ) за
4
 
ил

су
М

Слика 1.5 Резултат израчунавања израза (1.9).


а
1.

ав
02

пр
–2

4
а
20

Св
20

− 7 3
а.
©

Слика 1.6 Хиjерархиjски


иj

приказ израчунавања
израза (1.9). + 4 3 + 2 1
рз
ве
на

Префиксна нотациjа омогућава придруживање произвољног броjа опе-


ранада jедном оператору, што ћемо илустровати следећим примером.
д
Ра

Пример 1.4. Jедан од начина да се инфиксни запис:

1+2+3+4+5 (1.10)

представи у префиксноj нотациjи jе:

1
На разматрање ове претпоставке вратићемо се у 2. поглављу (в. примере 2.6 и 2.10).
1.2 Аритметички изрази и префиксна нотациjа 7

(+ (+ (+ (+ 1 2) 3) 4) 5) . (1.11)

Међутим, префиксна нотациjа омогућава да се запис (1.11) представи у


jедноставниjоj форми:
(+ 1 2 3 4 5) . (1.12)
На сл. 1.7 види се да су резултати израчунавања израза (1.11) и (1.12)
jеднаки.

 
> (+ (+ (+ (+ 1 2 ) 3 ) 4 ) 5 )
15
> (+ 1 2 3 4 5 )
15
 
.
ић
Слика 1.7 Резултати израчунавања израза (1.11) и (1.12).
ов

а.
ат

Слично, изрази:

ан
Гњ

ж
(− 1 2 3), (∗ 1 2 3), (/ 1 2 3) , (1.13)

др
ан

еквивалентни су, респективно, изразима:


за
ил

(− (− 1 2) 3) ,
су
М

(∗ (∗ 1 2) 3) , (1.14)
а

(/ (/ 1 2) 3) ,
1.

ав
02

пр

а резултати њиховог израчунавања дати су на сл. 1.8.


–2

 
20

Св

> (− 1 2 3)
20

−4
а.

> (− (− 1 2 ) 3 )
©

иj

−4
> (∗ 1 2 3)
рз

6
ве

> (∗ (∗ 1 2) 3)
6
на

> (/ 1 2 3)
1
д

6
> ( / ( / 1 2) 3)
Ра

1
6 

Слика 1.8 Резултати израчунавања израза (1.13) и (1.14).

Пример 1.5. Префиксна нотациjа допушта произвољни ниво угнежђива-


ња заграда, што може довести до тога да изрази постану релативно за-
8 1 Атомски типови података

метни за људско интерпретирање. Да би се олакшало људско интерпрети-


рање, компликовани изрази уобичаjено се наводе тако да делови израза
коjи се налазе на истом хиjерархиjском нивоу буду вертикално поравна-
ти. Нпр., израз:

(+ (− (/ (+ 34 14) (/ 16 4)) (∗ (/ 8 4) (− 8 5 1))) (∗ (− 5 2) 3)) (1.15)

може се написати у читљивиjоj форми приказаноj на сл. 1.9.

(+ (− ( / (+ 34 1 4 )
( / 16 4 ) )
(∗ ( / 8 4)
(− 8 5 1 ) ) )
( ∗ (− 5 2 ) 3 ) )
.
ић
ов
Слика 1.9 Читљивиjи запис израза (1.15).

а.
ат

ан
Гњ

У неким програмским jезицима, вертикално поравнање линиjа ко̂да

ж
носи информациjу о структури ко̂да, док у другим програмским jезици-

др
ма (укључуjући Ракет) оно само доприноси читљивости ко̂да. У сваком
ан

за
случаjу, програмер треба да усвоjи и примењуjе одговараjући стил писа-
ил

ња читљивог ко̂да, jер тиме олакшава (људско) интерпретирање и одр-


су

жавање програма, што jе од посебног значаjа ако су програми високог


М

степена сложености, развиjани током дужег периода и од стране тима


а
1.

ав

програмера.
02

пр
–2

а
20

Св

1.3 Броjеви и изабране аритметичке операциjе


20

а.

Броjеве можемо поделити по два критериjума. Прва подела, каракте-


©

иj

ристична за математичке скупове броjева, односи се на врсте броjева:


рз

• цели броjеви Z,
ве

• рационални броjеви Q,
• реални броjеви R,
на

• комплексни броjеви C,
д

при чему сваки од наведених скупова броjева представља подскуп скупа


Ра

броjева коjи му непосредно следи, тj.:

Z⊂Q⊂R⊂C. (1.16)

Док сви броjеви формално припадаjу скупу комплексних броjева, прак-


тичне примене често се засниваjу на претпоставци да броjеви припадаjу
1.3 Броjеви и изабране аритметичке операциjе 9

одређеном подскупу броjева (што ћемо размотрити касниjе). „Каракте-


ристични” примери елемената сваког од ових скупова дати2 су у табели
1.1.

Табела 1.1 Примери елемената скупова броjева.

Скуп броjева Примери елемената

Z, цели броjеви: 0, 1, −2
Q, рационални броjеви: 21 , − 34 , 32
R, реални броjеви: 1, 2, 3, 45, −0, 3333333333333333
C, комплексни броjеви: i, 1 + 3i, 5 − 6i

.
ић
Пример 1.6. Примери основних аритметичких операциjа над комплек-
ов

сним броjевима дати су на сл. 1.10.

а.
ат

ан
 
Гњ

ж
> (+ 2+1 i 3+4 i )

др
5+5 i
ан

> (− 2+1 i 3+4 i ) за


−1−3i
ил

> ( ∗ 2+1 i 3+4 i )


су

2+11 i
М

> ( / 2+1 i 3+4 i )


а

2 /5 − 1/5i
1.

ав

 
02

пр

Слика 1.10 Примери основних аритметичких операциjа над комплексним броjевима.


–2

а
20

Св
20

Пример 1.7. Резултат примене аритметичких оператора +, −, ∗ и / за-


а.
©

виси од врсте броjева над коjима се оператори примењуjу. Ова зависност


иj

илустрована jе на сл. 1.11. Нпр., резултат сабирања целих броjева тако-


рз

ђе jе цели броj ((+ 1 2) → 3). Међутим, ако бар jедан сабирак ниjе цео
броj, збир ниjе целоброjни ((+ 1.0 2) → 3.0). Аналогне напомене важе и
ве

за друге аритметичке операторе.


на

Овим долазимо до друге поделе броjева, коjа jе последица рачунарског


д

представљања броjева, што подразумева да jе за представљање броjа до-


Ра

ступан ограничени мемориjски простор. У односу на оваj критериjум,


броjеви се деле на прецизне и непрецизне. Прецизни броjеви укључуjу:

2
За запис реалних броjева датих у табели 1.1 коришћен jе зарез као децимални
сепаратор, што jе уобичаjена пракса у Србиjи. У програмским jезицима, укључуjући
Ракет, уобичаjено се користи тачка као децимални сепаратор, што намеће обавезу да
пратимо ово правило приликом писања изворних програмских ко̂дова.
10 1 Атомски типови података
 
> (+ 1 2)
3
> (+ 1.0 2)
3.0
> (− 1 2)
−1
> (− 1 2.0)
−1 . 0
> (∗ 1 2)
2
> (∗ 1 2.0)
2.0
> (/ 1 2)
1 /2
> (/ 1.0 2)
0.5

. 
ић
ов
Слика 1.11 Илустрациjа зависности резултата примене аритметичких оператора +,

а.
−, ∗ и / од врсте операнада.
ат

ан
Гњ

ж
• целe броjевe,

др
• рационалнe броjевe чиjи су броjиоци и имениоци цели броjеви,
ан

за
• комплекснe броjевe чиjи су реални и имагинарни делови прецизни бро-
ил

jеви.
су
М

Непрецизни броjеви укључуjу:


а
1.

ав

• реалне броjеве (тj., броjеве чиjи запис садржи децимални зарез или
02

експонент e, и специjалне вредности попут +inf.0, −inf.0 и +nan.0),


пр

• комплекснe броjевe чиjи су реални или имагинарни делови непрецизни


–2

броjеви.
а
20

Св

Пример 1.8. Ракет чува прецизност броjева кад год jе то могуће. Нпр.,
20

приликом израчунавања вредности израза:


а.
©

иj

(/ 3 9) , (1.17)
рз

3 1
ве

разломак своди се на , уз очување прецизности резултата (в. сл. 1.12).


9 3
на

 
д
Ра

> ( / 3 9)
1
3 

Слика 1.12 Свођење резултата израчунавања аритметичког израза (1.17), уз очува-


ње прецизности.

С друге стране, вредност израза:


1.3 Броjеви и изабране аритметичке операциjе 11

(/ 3.0 9.0) , (1.18)

садржи, у теориjи, неограничени броj децимала (0, 333 . . .), па се због


ограничености доступног мемориjског простора не може представити у
целини. Због тога jе рачунарско представљање резултата израчунавања
овог израза приближно, тj., непрецизно, jер jе само коначни подскуп де-
цимала резултата узет у обзир (в. сл. 1.13).

 
> (/ 3.0 9.0)
0.3333333333333333
 

Слика 1.13 Непрецизно свођење резултата израчунавања аритметичког израза


(1.18).
.
ић
ов

а.
Може се стећи утисак да jе губитак прецизности занемарљив, али то,
ат

ан
у општем случаjу, ниjе тачно. Примена аритметичких оператора над не-
Гњ

ж
прецизним броjевима захтева извесну пажњу, jер чим jе jедан операнд

др
непрецизни броj, резултат jе такође непрецизан.
ан

за
Пример 1.9. Ако упоредимо резултате непрецизног одузимања броjева
ил

приказане на сл. 1.14, приметићемо да се разликуjу, иако би се очекивало


су

да буду исти. Превазилажење овог проблема размотрићемо у 2. поглављу


М

(в. пример 2.29).


а
1.

ав
02

 
пр

> (− 1 0 . 9 )
–2

0.09999999999999998
а
20

> (− 2 1 . 9 )
Св

0.10000000000000009
20

 
а.
©

иj

Слика 1.14 Пример непрецизног одузимања броjева.


рз
ве

У примеру 1.7 посматрали смо зависност резултатa примене аритме-


на

тичких оператора од врсте операнада. Размотримо сад специфичне слу-


чаjеве ове зависности, да бисмо обjаснили три3 специjалне вредности:
д
Ра

• +inf.0 — непрецизни реални броj коjи представља позитивну бесконач-


ност,
• −inf.0 — непрецизни реални броj коjи представља негативну бесконач-
ност,
3
Скуп специjалних вредности у програмском jезику Ракет превазилази три наведене
вредности. Међутим, овде посматрамо само вредности +inf.0, −inf.0 и +nan.0 као
индикативне за остале елементе у скупу специjалних вредности.
12 1 Атомски типови података

• +nan.0 — непрецизни реални броj коjи се односи на вредности коjе


нису дефинисане или се не могу представити (тзв. неброj, енгл. not-a-
number ).

Пример 1.10. Настављаjући се на пример 1.8, можемо приметити да за-


пис 0 представља прецизну вредност нуле, док запис 0.0 представља не-
прецизну вредност нуле. Ако покушамо да поделимо неки броj прецизном
вредношћу нуле, индиковаће се грешка у израчунавању. Међутим, ако
броj поделимо непрецизном вредношћу нуле, резултат зависи од вредно-
сти дељеника:
• ако jе дељеник позитивни броj, резултат дељења биће jеднак позитив-
ноj бесконачности +inf.0,
• ако jе дељеник негативни броj, резултат дељења биће jеднак негативноj
бесконачности −inf.0,
.
ић
• ако jе дељеник jеднак прецизноj вредности нуле, резултат дељења биће
ов

jеднак прецизноj вредности нуле,

а.
• ако jе дељеник jеднак непрецизноj вредности нуле, резултат дељења
ат

ан
биће jеднак специjалноj вредности +nan.0.
Гњ

ж
Примери свих наведених случаjева дати су на сл. 1.15.

др
ан


за 
ил

> ( / 1 0)
су

. . . / : d i v i s i o n by z e r o
М

> (/ 1 0.0)
а

+i n f . 0
1.

ав

> ( / −1 0 . 0 )
02

пр

−inf . 0
> (/ 0 0.0)
–2

0
а
20

Св

> (/ 0.0 0.0)


+nan . 0
20

 
а.
©

иj

Слика 1.15 Илустрациjа зависности резултата дељења нулом од дељеника.


рз
ве

Операциjе сабирања, одузимања, множења и дељења представљаjу са-


на

мо jедан подскуп унапред дефинисаних операциjа над броjевима. У на-


ставку ћемо размотрити изабране аритметичке операциjе коjе подразу-
д
Ра

меваjу да операнди припадаjу одређеном подскупу броjева. Ове опера-


циjе ћемо називати функциjама, а вредности коjе им се саопштаваjу —
улазним аргументима (поjам функциjе ће бити детаљниjе описан у 2. по-
глављу). Приликом позивања функциjа доследно се држимо изложених
правила префиксне нотациjе:

(назив-функциjе аргумент аргумент . . . ) , (1.19)


1.3 Броjеви и изабране аритметичке операциjе 13

тj., изрази се наводе у облим заградама, а називи функциjа се наводе


испред улазних аргумената.
Пример 1.11. Као примере функциjа коjе прихватаjу целоброjне аргумен-
те посматраћемо quotient и remainder. Функциjа quotient прихвата два
цела броjа и враћа количник целоброjног дељења првог броjа другим,
што jе илустровано на сл. 1.16. Ова функциjа генерише одговараjући ре-
зултат чак и ако jоj се саопште реални броjеви коjи се без губитака могу
конвертовати у целе броjеве, при чему jе резултат такође реални броj.
Међутим, ако конверзиjа реалних броjева у целе броjеве ниjе могућа без
губитака, индикуjе се грешка.

 
> ( quotient 9 4)
2
.
ић
> ( q u o t i e n t −17 5 )
−3
ов

а.
> ( quotient 9.0 4.0)
ат

ан
2.0
> ( quotient 9.1 4) ← неодговараjући тип улазног аргумента
Гњ

ж
. . . quotient : contract violation

др
expected : i n t e g e r ?
given : 9.1
ан

argument p o s i t i o n : 1 s t
за
ил

o t h e r arguments . . . :
 
су
М

Слика 1.16 Илустрациjа функциjе quotient.


1.

ав
02

пр

Функциjа remainder прихвата два целоброjна операнда, и враћа оста-


–2

так целоброjног дељења првог операнда другим. Ова функциjа такође


а
20

генерише одговараjући резултат у случаjу да jоj се саопште реални бро-


Св

jеви коjи се без губитака могу конвертовати у целе броjеве, при чему jе
20

резултат такође реални броj (в. сл. 1.17).


а.
©

Jедна од честих примена функциjа quotient и remainder односи се на


иj

издваjање цифара из целих броjева. Уклањање последње цифре из датог


рз

целог броjа x врши се позивањем функциjе (quotient x 10), док се по-


ве

следња цифра броjа x добиjа позивањем функциjе (remainder x 10). Ово


jе илустровано за цели броj 12345 на сл. 1.18.
на

Пример 1.12. Као примере функциjа коjе прихватаjу рационалне аргу-


д
Ра

менте посматраћемо numerator и denominator. Функциjа numerator при-


хвата рационални броj и враћа његов броjилац, а функциjа denominator
прихвата рационални броj и враћа његов именилац. У примерима датим
на сл. 1.19 и 1.20, приказано jе понашање ових функциjа кад им се са-
опште цели броjеви или броjеви с децималним сепаратором. Нпр., броj
2 1.0
2 се своди на , а броj 0, 25 на . Кад се овим функциjама проследи
1 4.0
комплексни броj, индикуjе се грешка.
14 1 Атомски типови података
 
> ( remainder 9 4)
1
> ( r e m a i n d e r −17 5 )
−2
> ( remainder 9.0 4 . 0 )
1.0
> ( remainder 9.1 4) ← неодговараjући тип улазног аргумента
. . remainder : c o n t r a c t v i o l a t i o n
expected : i n t e g e r ?
given : 9.1
argument p o s i t i o n : 1 s t
o t h e r arguments . . . :
 

Слика 1.17 Илустрациjа функциjе remainder.


 
.
ић
> ( q u o t i e n t 12345 1 0 )
1234
ов

а.
> ( r e m a i n d e r 12345 1 0 )
ат

ан
5
 
Гњ

ж
др
Слика 1.18 Илустрациjа издваjања цифара из целог броjа.
ан

 за 
> ( numerator 3 /4 )
ил

3
су
М

> ( numerator −3/4 )


−3
а
1.

ав

> ( numerator 2 )
2
02

пр

> ( numerator 0 . 2 5 )
–2

1.0
а

> ( numerator 2+3 i ) ← неодговараjући тип улазног аргумента


20

Св

. . . numerator : c o n t r a c t v i o l a t i o n
20

expected : r a t i o n a l ?
g i v e n : 2+3 i
а.
©

 
иj
рз

Слика 1.19 Илустрациjа функциjе numerator.


ве

Пример 1.13. Као групу функциjа коjе прихватаjу реалне аргументе по-
на

сматраћемо truncate, floor , ceiling и round. Све ове функциjе прихватаjу


д

по jедан реални аргумент x, и враћаjу следеће вредности:


Ра

• truncate враћа цели броj коjи се добиjе кад се из x уклони децимални


део (тj., децимални сепаратор и цифре иза њега),
• floor враћа наjвећи цели броj коjи jе мањи или jеднак x,
• ceiling враћа наjмањи цели броj коjи jе већи или jеднак x,
1.3 Броjеви и изабране аритметичке операциjе 15
 
> ( denominator 3 /4 )
4
> ( denominator −3/4 )
4
> ( denominator 2 )
1
> ( denominator 0 . 2 5 )
4.0
> ( denominator 2+3 i ) ← неодговараjући тип улазног аргумента
. . . denominator : c o n t r a c t v i o l a t i o n
expected : r a t i o n a l ?
g i v e n : 2+3 i
 

Слика 1.20 Илустрациjа функциjе denominator.

.
ић
• round заокружуjе x на наjближи цели броj — ако jе x подjеднако удаљен
ов

а.
од два суседна цела броjа, заокруживање се врши на наjближи парни
ат

ан
цели броj,
Гњ

ж
што jе илустровано на сл. 1.21. Кад се овим функциjама проследи ком-

др
плексни броj, индикуjе се грешка.
ан

за
 
ил

су
> ( truncate 9.3)
М

9.0
а

> ( t r u n c a t e −9 . 3 )
1.

ав

−9 . 0
02

> ( floor 9.3)


пр

9.0
–2

> ( f l o o r −9 . 3 )
а

−10 . 0
20

Св

> ( ceiling 9.3)


20

10.0
а.

> ( c e i l i n g −9 . 3 )
©

−9 . 0
иj

> ( round 9 . 3 )
рз

9.0
> ( round 9 . 5 )
ве

10.0
> ( round 1 0 . 5 )
на

10.0
д

> ( t r u n c a t e 3 − 5i ) ← неодговараjући тип улазног аргумента


Ра

. . truncate : contract violation


expected : r e a l ?
g i v e n : 3 − 5i
 

Слика 1.21 Илустрациjа функциja truncate, floor , ceiling и round.


16 1 Атомски типови података

Пример 1.14. Као групу функциjа коjе прихватаjу комплексне аргумен-


те посматраћемо функциjе real−part, imag−part, expt и sqrt. Функциjе
real−part и imag−part прихватаjу комплексни броj, и враћаjу његов ре-
ални, односно имагинарни део. Функциjа expt прихвата два броjа x и y, и
враћа вредност xy , а функциjа sqrt прихвата броj x, и враћа вредност x̂,
тако да важи x = x̂2 , што jе илустровано на сл. 1.22. Пошто скуп комплек-
сних броjева по дефинициjи садржи реалне, рационалне и целе броjеве,
то значи да функциjама коjе прихватаjу комплексне броjеве можемо про-
следити4 улазне аргументе из произвољног подскупа броjева.

 
> ( r e a l − p a r t 1+2 i )
1
> ( imag − part 1+2 i )
2
.
ић
> ( expt 2 3)
ов
8

а.
> ( e x p t 9 1 /2 )
ат

ан
3
Гњ

> ( e x p t −1 1 /2 )

ж
0+1 i

др
> ( e x p t 1+1 i 2 )
ан

0+2 i за
> ( s q r t 4)
ил

2
су

> ( s q r t 2)
М

1.4142135623730951
а

> ( s q r t −1)
1.

ав

0+1 i
02

 
пр
–2

Слика 1.22 Илустрациjа функциja real −part, imag−part, expt и sqrt.


а
20

Св
20

а.
©

иj
рз

1.4 Буловске вредности и функциjе


ве

Други важни тип података односи се на буловске вредности. Домен


на

овог типа чине две вредности:


д

• тачно — коjа се у синтакси програмског jезика Ракет означава #t,


Ра

• нетачно — коjа се у синтакси програмског jезика Ракет означава #f.


До сад смо разматрали аритметичке операциjе коjе као улазне аргумен-
те прихватаjу jедан броj или више њих, и чиjи jе резултат израчунавања

4
Ово не уклања ограничења условљена дефинициjом функциjе, попут забране деље-
ња прецизном вредношћу нуле.
1.4 Буловске вредности и функциjе 17

броj. У наставку ћемо размотрити операциjе релациjе коjе такође при-


хватаjу броjеве као улазне аргументе, али као резултат израчунавања
враћаjу буловске вредности:
• = враћа вредност #t ако су сви улазни аргументи jеднаки, а у супрот-
ном враћа вредност #f,
• < враћа вредност #t ако jе низ улазних аргумената строго растући, а
у супротном враћа вредност #f,
• <= враћа вредност #t ако jе низ улазних аргумената монотоно нео-
падаjући, а у супротном враћа вредност #f,
• > враћа вредност #t ако jе низ улазних аргумената строго опадаjући,
а у супротном враћа вредност #f,
• >= враћа вредност #t ако jе низ улазних аргумената монотоно нера-
стући, а у супротном враћа вредност #f.
.
ић
Пример 1.15. Операциjе релациjе су илустроване на сл. 1.23. Треба при-
ов

метити да се операциjи jеднакости могу саопштити сви броjеви, док се

а.
осталим операциjама релациjе могу саопштити реални броjеви, али не
ат

ан
и комплексни броjеви с ненултим имагинарним деловима — за пример
Гњ

ж
поређења оваквих броjева в. пример 2.8, у 2. поглављу.

др
ан

Буловске вредности такође могу да се прослеђуjу функциjама као ула-


за
зни аргументи. Основне буловске функциjе су конjункциja (and), дис-
ил

jункциjа (or) и негациjа (not). Домене и кодомене ових функциjа ћемо


су
М

ограничити5 на буловске вредности:


а
1.

• and прихвата низ буловских вредности као улазне аргументе, и враћа


ав
02

вредност #t ако су сви улазни аргументи jеднаки #t, а у супротном


пр

враћа вредност #f,


–2

• or прихвата низ буловских вредности као улазне аргументе, и враћа


а
20

Св

вредност #t ако jе бар jедан улазни аргумент jеднак #t, а у супротном


20

враћа вредност #f,


а.

• not прихвата jедну буловску вредност као улазни аргумент, и враћа


©

иj

вредност #t ако jе улазни аргумент jеднак #f, а у супротном враћа


вредност #t.
рз
ве

Пример 1.16. Основне буловске функциjе (конjункциjа, дисjункциjа и не-


гациjа) илустроване су на сл. 1.24.
на

Пример 1.17. Посматраjмо следећи израз:


д
Ра

(or (and (> 5 3) (= 1 2)) (not (= (+ 1 2) (− 3 4))) #f) . (1.20)

5
У програмском jезику Ракет, буловске функциjе прихватаjу и улазне аргументе
коjи нису буловске вредности, и враћаjу вредности коjе нису обавезно буловске (нпр.,
(and #t 1) → 1, (or 2 #f) → 2), али те аспекте ових функциjа нећемо овде разматрати.
18 1 Атомски типови података
 
> (= 2 2 . 0 )
#t
> (= 2 )
#t
> (= 1 2 )
#f
> (< 2 1 )
#f
> (< 1 2 3 )
#t
> (< 1 2 2 3 )
#f
> (<= 2 1 )
#f
> (<= 1 2 2 3 )
#t
.
ић
> (> 1 2 )
#f
ов

> (> 3 2 1 )

а.
#t
ат

ан
> (> 3 2 2 1 )
Гњ

#f

ж
(> 1 )

др
#t
ан

> (>= 3 2 2 1 )
за
#t
ил

> (>= 1 2 )
су
М

#f
> (= 1 2+3 i )
а
1.

ав

#f
> (< 1 2+3 i )
02

пр

. . . <: c o n t r a c t v i o l a t i o n
–2

expected : r e a l ?
а

g i v e n : 2+3 i
20

Св

argument p o s i t i o n : 2nd
20

o t h e r arguments . . . :
 
а.
©

иj

Слика 1.23 Илустрациjа операциjа релациjе.


рз
ве

Оваj израз комбинуjе броjеве и буловске вредности с аритметичким опе-


на

рациjама, операциjама релациjе и буловским функциjама. Овакве ком-


бинациjе су дозвољене све док су задовољени услови да израз синтак-
д

сно одговара префиксноj нотациjи, и да су типови вредности саопштених


Ра

функциjама одговараjући. Поступак израчунавања оваквих израза не ра-


зликуjе се од поступка израчунавања аритметичких израза описаног у
секциjи 1.2.
Кад се израз (1.20) саопшти интерпретатору, резултат израчунавања
jеднак jе #t (в. сл. 1.25). Приказ његовог израчунавања по корацима дат
jе на сл. 1.26, а хиjерархиjски приказ израчунавања дат jе на сл. 1.27.
1.4 Буловске вредности и функциjе 19
 
> ( and #t #t )
#t
> ( and #t #f )
#f
> ( and #f #t #f )
#f
> ( and #t )
#t
> ( or #f #f )
#f
> ( or #f #t )
#t
> ( or #f #t #f )
#t
> ( not #t )
#f
.
ић
> ( not #f )
#t
 
ов

а.
ат

ан
Слика 1.24 Илустрациjа буловских функциjа: конjункциjа, дисjункциjа и негациjа.
Гњ

ж
 

др
> ( or ( and (> 5 3 ) (= 1 2 ) ) ( not (= (+ 1 2 ) (− 3 4 ) ) ) #f )
ан

#t
 
за
ил

су

Слика 1.25 Резултат израчунавања израза (1.20).


М

( or ( and (> 5 3 ) (= 1 2 ) ) ( not (= (+ 1 2 ) (− 3 4 ) ) ) #f )


1.

ав

( or ( and #t #f ) ( not (= 3 −1 ) ) #f )
02

пр

( or #f ( not #f ) #f )
–2

( or #f #t #f )
а

#t
20

Св
20

Слика 1.26 Приказ израчунавања израза (1.20) по корацима.


а.
©

иj

#t
рз
ве

or #f #t #f
на

and #t #f not #f
д
Ра

> 5 3 = 1 2 = 3 −1

+ 1 2 − 3 4

Слика 1.27 Хиjерархиjски приказ израчунавања израза (1.20).


20 1 Атомски типови података

Поређење буловских вредности врши се функциjом boolean=?. Ова


функциjа прихвата две буловске вредности као улазне аргументе, и утвр-
ђуjе да ли су jеднаке.

Пример 1.18. Функциjа boolean=? илустрована jе на сл. 1.28. Кад се овоj


функциjи саопшти неодговараjући броj улазних аргумената или улазни
аргумент неодговараjућег типа, индикуjе се грешка.

 
> ( boolean=? #t #f )
#f
> ( boolean=? #t #t )
#t
> ( boolean=? #t #t #t ) ← неодговараjући броj улазних аргумената
. . . boolean=? : a r i t y mismatch ;
.
ић
t h e e x p e c t e d number o f arguments d o e s not match t h e g i v e n number
expected : 2
ов

given : 3

а.
arguments . . . :
ат

ан
> ( boolean=? #t 1 ) ← неодговараjући тип улазног аргумента
Гњ

ж
. . . boolean=? : c o n t r a c t v i o l a t i o n
expected : boolean?

др
given : 1
ан

argument p o s i t i o n : 2nd
за
o t h e r arguments . . . :
ил

 
су
М

Слика 1.28 Илустрациjа функциjе boolean=?.


а
1.

ав
02

пр
–2

а
20

Св

1.4.1 Предикати
20

а.
©

Предикати су функциjе коjе прихватаjу jедан улазни аргумент, и утвр-


иj

ђуjу да ли припада одређеноj класи података. Уколико улазни аргумент


рз

припада датоj класи података, предикати враћаjу вредност #t, а у су-


ве

протном вредност #f. Предикати коjи се односе на броjеве су следећи:


на

• number? утврђуjе да ли jе улазни аргумент броj,


• complex? утврђуjе да ли jе улазни аргумент комплексни броj,
д

• real? утврђуjе да ли jе улазни аргумент реални броj,


Ра

• rational ? утврђуjе да ли jе улазни аргумент рационални броj,


• integer? утврђуjе да ли jе улазни аргумент цели броj,
• exact? утврђуjе да ли jе улазни аргумент прецизни броj,
• inexact? утврђуjе да ли jе улазни аргумент непрецизни броj,
а предикат boolean? утврђуjе да ли jе улазни аргумент буловска вредност.
1.4 Буловске вредности и функциjе 21

Пример 1.19. У табели 1.2 приказане су повратне вредности предиката


кад им се саопште изабрани улазни аргументи. Jедна повратна вредност,
истакнута на сл. 1.29, може се учинити неочекиваном. Позив функциjе
( rational ? 3.4) враћа вредност #t, што значи да jе улазни аргумент 3.4
индикован као рационални броj. То jе последица дизаjна програмског
jезика Ракет: сви реални броjеви коjи се могу представити, тj., сви реални
броjеви осим специjалних вредности6 , по дефинициjи су и рационални
броjеви.

Табела 1.2 Илустрациjа изабраних предиката коjи се односе на броjеве.

1 2 3.4 4 + 5i 4 + 5.0i +inf.0 +nan.0 #t


3
number? #t #t #t #t
. #t #t #t #f
ић
complex? #t #t #t #t #t #t #t #f
ов
real ? #t #t #t #f #f #t #t #f

а.
rational ? #t #t #t #f #f #f #f #f
ат

ан
integer? #t #f #f #f #f #f #f #f
exact? #t #t #f #t #f #f #f #f
Гњ

ж
inexact? #f #f #t #f #t #t #t #f

др
ан

за
ил

су

 
М

> ( rational? 3.4)


а

#t
1.

ав

 
02

пр
–2

Слика 1.29 Илустрациjа функциjе rational ?.


а
20

Св
20

Пример 1.20. Функциjа boolean? jе илустрована на сл. 1.30.


а.
©

иj

 
рз

> ( b o o l e a n ? #f )
#t
ве

> ( boolean? 1)
#f
на

 
д
Ра

Слика 1.30 Илустрациjа функциjе boolean?.

За друге типове података такође постоjе одговараjући предикати. Неке


од њих размотрићемо у наставку.
6
Подсетимо се да су специjалне вредности, попут +inf.0, −inf.0 и +nan.0, у програм-
ском jезику Ракет дефинисане као реални броjеви.
22 1 Атомски типови података

1.5 Стрингови

Осим броjевима и буловским вредностима, подаци се могу предста-


вљати и симболички, тj., у форми текста. Текстуалне податке називамо
стринговима. У општем случаjу, стринг jе низ симбола написаних између
наводника7 (") испред коjих ниjе наведена обрнута коса црта (\). Неки
примери стрингова су:
• "основи програмирања",
• "osnovi programiranja",
• "Добар дан!",
• "Sastanak je u 10.",
• "12345",
• "".
.
ић
Последња вредност представља тзв. празни стринг, тj., стринг коjи не
ов

садржи ниjедан симбол.

а.
Стрингови могу да садрже слова различитих писама, празни простор,
ат

ан
цифре, знакове интерпункциjе, итд. — укључуjући и специjалне симбо-
Гњ

ж
ле. Специjални симболи се представљаjу знаковним биграмима коjе чине

др
обрнута коса црта (\) и симбол. Неки од специjалних симбола су:
ан

за
• \n означава прелазак у нови ред,
ил

• \t означава хоризонтални помераj,


су

• \"означава наводник,
М

• \’ означава полунаводник,
а
1.

ав

• \\ означава обрнуту косу црту.


02

пр

Пример 1.21. Употреба специjалних симбола у стринговима илустрована


–2

jе на сл. 1.31. Исписивање стрингова врши се функциjом display.


а
20

Св
20

 
а.

> ( d i s p l a y " n o v i \ nred " )


©

novi
иj

red
рз

> ( d i s p l a y " h o r i z o n t a l n i \ trazmak " )


horizontalni razmak
ве

> ( d i s p l a y "\" n a v o d n i c i \ " " )


" navodnici "
на

> ( d i s p l a y "\ ’ p o l u n a v o d n i c i \ ’ " )


д

’polunavodnici’
Ра

> ( d i s p l a y " obrnuta kosa c r t a : \\")


obrnuta kosa c r t a : \
 

Слика 1.31 Илустрациjа исписивања стрингова са специjалним симболима.

7
Овде се мисли на наводнике коjи се користе у енглеском правопису, а не у српском.
1.5 Стрингови 23

Броj елемената у стрингу уобичаjено се назива дужином стринга. Сва-


ком симболу у непразном стрингу додељуjе се индекс коjи означава по-
зициjу симбола у стрингу. Првом симболу у стрингу додељуjе се индекс
0, другом симболу индекс 1, итд. — симболу коjи се налази на редном
месту i додељуjе се индекс i − 1, a последњем симболу индекс l − 1, где jе
l дужина стринга.

Пример 1.22. Додељивање индекса симболима у стрингу приказано jе


на сл. 1.32. За представљање латиничног диграфа ’nj’ користе се два
симбола (n, j), за разлику од ћириличног слова ’њ’, коjе се представља
jедним симболом. Због тога je дужина стринга "основи програмирања"
jеднака 19, док jе дужина стринга "osnovi programiranja" jеднака 20. С
друге стране, специjални симболи, попут \", интерпретираjу се као jе-
дан симбол, иако се ради о знаковном биграму, па jе дужина стринга
.
ић
"\"navodnici\"" jеднака 11 (в. сл. 1.33).
ов

а.
ат

стринг: о с н о в и ␣ п р о г р а м и р а њ а

ан
индекси: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
Гњ

ж
стринг: o s n o v i ␣ p r o g r a m i r a n j a

др
индекси: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
ан

за
стринг: \" n a v o d n i c i \"
ил

индекси: 0 1 2 3 4 5 6 7 8 9 10
су
М

Слика 1.32 Индекси симбола у стринговима.


а
1.

ав
02

пр
–2

Размотримо основне операциjе над стринговима:


а
20

• Функциjа string−append прихвата низ стрингова као улазне аргумен-


Св

те, и враћа стринг коjи се добиjа спаjањем елемената улазног низа


20

стрингова. Улазни стрингови се спаjаjу у редоследу у коjем су саоп-


а.
©

штени функциjи. Ако jе улазни низ празан, функциjа string−append


иj

враћа празни стринг.


рз

• Функциjа string−length прихвата jедан стринг као улазни аргумент, и


ве

враћа његову дужину.


• Функциjа substring прихвата три улазна аргумента:
на

1. стринг s дужине l,
д
Ра

2. ненегативни цели броj i


3. ненегативни цели броj j, при чему jе оваj улазни аргумент опцион —
ако ниjе експлицитно задат, његова подразумевана вредност jеднака
jе l.
Ако су улазни аргументи такви да важи:

0≤i≤ j≤l, (1.21)


24 1 Атомски типови података

функциjа substring враћа подстринг коjи почиње симболом коjем jе до-


дељен индекс i у стрингу s, а завршава се симболом коjем jе додељен
индекс j − 1 у стрингу s. У специjалном случаjу кад важи i = j, функ-
циjа substring враћа празни стринг. Ако услов (1.21) ниjе задовољен,
индикуjе се грешка.

Пример 1.23. Функциjа string−length илустрована jе на сл. 1.33.

 
> ( string − length "основи програмирања " )
19
> ( string − length " osnovi programiranja ")
20
> ( string − length "\" n a v o d n i c i \ " " )
11
.
ић
> ( string − length " n o v i \ nred " )
8
ов

> ( string − length "")

а.
0
ат

ан
 
Гњ

ж
Слика 1.33 Илустрациjа функциjе string −length.

др
ан

за
ил

Пример 1.24. Функциjа string−append илустрована jе на сл. 1.34.


су
М

 
1.

ав

> ( s t r i n g − a p p e n d " dobar " " dan " )


02

" dobardan "


пр

> ( s t r i n g − a p p e n d " dobar " " " " dan " )


–2

" dobar dan "


а
20

> ( s t r i n g − a p p e n d " dob " " a r d" " an " )


Св

" dobar dan "


20

 
а.
©

иj

Слика 1.34 Илустрациjа функциjе string −append.


рз
ве

Пример 1.25. Функциjа substring илустрована jе на сл. 1.35.


на

Функциjе коjе имплементираjу операциjе релациjе између стрингова


д

прихватаjу низ стрингова као улазне аргументе, а као резултат враћаjу


Ра

буловске вредности:
• функциjа string=? враћа вредност #t ако су сви улазни аргументи
jеднаки, а у супротном враћа вредност #f,
• функциjа string<? враћа вредност #t ако jе низ улазних аргумена-
та лексикографски уређен као строго растући, а у супротном враћа
вредност #f,
1.5 Стрингови 25
 
> ( substring " o s n o v i p r o g r a m i r a n j a " 1 6 )
" snovi "
> ( substring " o s n o v i p r o g r a m i r a n j a " 7 1 5 )
" p r o g r a mi "
> ( substring " o s n o v i p r o g r a m i r a n j a " 7 )
" programiranja "
> ( substring " o s n o v i p r o g r a m i r a n j a " 7 7 )
""
> ( substring " o s n o v i p r o g r a m i r a n j a " 1 3 0 ) ← прекорачење опсега индекса
. . . substring : e n d i n g i n d e x i s out o f r a n g e
e n d i n g i n d e x : 30
s t a r t i n g index : 1
v a l i d range : [ 0 , 20]
s t r i n g : " osnovi programiranja "
 

.
ић
Слика 1.35 Илустрациjа функциjе substring.
ов

а.
ат

• функциjа string<=? враћа вредност #t ако jе низ улазних аргумена-

ан
та лексикографски уређен као монотоно неопадаjући, а у супротном
Гњ

ж
враћа вредност #f,

др
• функциjа string>? враћа вредност #t ако jе низ улазних аргумената
ан

лексикографски уређен као строго опадаjући, а у супротном враћа


за
ил

вредност #f,
су

• функциjа string>=? враћа вредност #t ако jе низ улазних аргумената


М

лексикографски уређен као монотоно нерастући, а у супротном враћа


а

вредност #f.
1.

ав
02

пр

Пример 1.26. Операциjе релациjе између стрингова илустроване су на сл.


–2

1.36.
а
20

Св

Предикат string? утврђуjе да ли jе улазни аргумент стринг.


20

а.

Пример 1.27. Функциjа string? jе илустрована на сл. 1.37.


©

иj
рз
ве

1.5.1 Експлицитна конверзиjа између броjева и


стрингова
д на
Ра

Под одређеним условима, програмски jезици омогућаваjу конверзиjе


вредности из jедног типа података у други. Конверзиjу коjу програмер
експлицитно задаjе у програмском ко̂ду називамо експлицитном конвер-
зиjом. Конверзиjу коjу програмски преводилац или интерпретатор извр-
шаваjу без експлицитног задавања од стране програмера називамо им-
26 1 Атомски типови података
 
> ( s t r i n g = ? " dan " " dan " )
#t
> ( s t r i n g = ? " dan " " dan " )
#f
> ( s t r i n g = ? " dan " "Dan " )
#f
> ( string<? " a n a l i z a " " metodologija " " podaci ")
#t
> ( string<? " a n a l i z a " " a n a l i z i r a t i ")
#t
> ( string<=? " a " " a " "b " )
#t
> ( string>? " a n a l i z a " " metodologija ")
#f
> ( string>=? "b" " a " "b " )
#f

. 
ић
ов
Слика 1.36 Илустрациjа операциjа релациjе између стрингова.

а.
ат

 

ан
> ( s t r i n g ? "12345")
Гњ

ж
#t

др
> ( s t r i n g ? 12345)
#f
ан

 
за
ил

су
Слика 1.37 Илустрациjа функциjе string ?.
М

а
1.

ав

плицитном конверзиjом8 . Овде ћемо размотрити изабране аспекте ек-


02

пр

сплицитне конверзиjе између броjева и стрингова.


–2

Функциjа number−>string прихвата два улазна аргумента:


а
20

Св

• броj n,
20

• основу броjног система b ∈ {2, 8, 10, 16}, при чему jе оваj улазни ар-
а.

гумент опцион — ако ниjе експлицитно задат, његова подразумевана


©

иj

вредност jеднака jе 10, а ако jе n непрецизни броj, вредност аргумента


b мора бити jеднака 10,
рз
ве

и враћа стринг коjи одговара броjу n записаном у броjном систему с


основом b.
на

Функциjа string−>number у своjоj основноj верзиjи9 прихвата два ула-


зна аргумента:
д
Ра

• стринг s,
8
Неки примери имплицитне конверзиjе између врста броjева размотрени су у примеру
1.7. Иако Ракет чува прецизност броjева кад год jе то могуће, имплицитне конверзиjе,
у општем случаjу, могу представљати ризик у развоjу софтвера, посебно ако про-
грамер ниjе свестан њиховог имплицитног извршавања или ниjе упознат с детаљима
њиховог извршавања.
9
Сложениjе дефинициjе ове фукциjе доступне су у [6].
1.6 Поређење вредности различитих типова података 27

• основy броjног система b ∈ {2, 3, . . . , 16}, при чему jе оваj улазни ар-
гумент опцион — ако ниjе експлицитно задат, његова подразумевана
вредност jеднака jе 10,
и враћа децимaлни броj коjи се добиjе кад се s интерпретира као броj за-
писан у броjном систему с основом b, или вредност #f ако улазни стринг
s не може да се конвертуjе у броj.
Пример 1.28. Функциjе number−>string и string−>number илустроване
су на сл. 1.38.

 
> ( number − >string 25)
"25"
> ( number − >string 25 2 )
"11001"
.
ић
> ( number − >string 25 1 6 )
ов
"19"

а.
> ( string − >number "101")
ат

ан
101
> ( string − >number "101" 2 )
Гњ

ж
5

др
> ( string − >number " abc " )
ан

#f за
 
ил

су

Слика 1.38 Илустрациjа функциjа number−>string и string −>number.


М

а
1.

ав
02

пр
–2

1.6 Поређење вредности различитих типова података


а
20

Св
20

За сваки атомски тип података коjи смо претходно размотрили на-


а.
©

ведена jе засебна функциjа коjа утврђуjе да ли су вредности улазних


иj

аргумената исте: функциjа = пореди броjеве, функциjа boolean=? бу-


рз

ловске вредности, а функциjа string=? стрингове. Међутим, ако се овим


функциjама саопште аргументи неодговараjућих типова података, инди-
ве

куjе се грешка (в. пример 1.18 и сл. 1.28). За разлику од њих, функциjа
на

equal? омогућава поређење вредности различитих типова података. Ова


функциjа прихвата два улазна аргумента произвољних типова података,
д
Ра

и утврђуjе да ли су њихове вредности jеднаке.


Пример 1.29. Функциjа equal=? je илустрована на сл. 1.39. Приликом по-
ређења броjева, ова функциjа у обзир узима не само вредности улазних
аргумената, већ и њихову прецизност, што обjашњава разлику између
повратних вредности функциjа equal? и = кад им се саопште улазни ар-
гументи истих вредности, али различитих прецизности, истакнуту на сл.
1.40.
28 1 Атомски типови података
 
> ( equal? 1 1)
#t
> ( equal? 1 1.0)
#f
> ( equal? #t #t )
#t
> ( equal? #t 1 )
#f
> ( equal? " dan " " dan " )
#t
> ( equal? " dan " #t )
#f
 

Слика 1.39 Илустрациjа функциjе equal?.


 
.
ић
> ( exact? 1)
#t
ов

а.
> ( exact? 1.0)
ат

ан
#f
> (= 1 1 . 0 )
Гњ

ж
#t

др
> ( equal? 1 1.0)
ан

#f
 
за
ил

су

Слика 1.40 Разлика између повратних вредности функциjа equal? и = кад им се


М

саопште улазни аргументи истих вредности, али различитих прецизности.


а
1.

ав
02

пр

1.7 Закључне напомене


–2

а
20

У овом поглављу размотрили смо изабране атомске типове података


Св

и операциjе над њима у програмском jезику Ракет. Међутим, важно jе


20

приметити да jе избор10 представљених атомских типова података вођен


а.
©

критериjумима њихове високе учесталости у практичним применама и


иj

присуством у великом броjу програмских jезика.


рз

Читаоцу коjи има искуства у раду с другим програмским jезицима, по-


ве

пут jезика Ц и Jава, може се учинити да класификациjа стринга као атом-


ског типа ниjе адекватна, jер се сваки непразни стринг може представити
на

као низ симбола. Одговор на ову примедбу би био да одређивање стринга


д

као атомског или сложеног типа података зависи од дизаjна конкретног


Ра

програмског jезика. У програмском jезику Ракет, симбол садржан у не-


празноме стрингу сматра се стрингом дужине jеднаке jедан, тj., сваки
непразни стринг може се представити као секвенца елемената чиjи типо-

10
Ракет садржи и друге атомске типове података (нпр., атомски тип података коjи
служи за представљање дигиталних слика), али они нису разматрани, jер су специ-
фични за дати програмски jезик.
1.8 Задаци 29

ви података такође одговараjу стрингу. За овакво декомпоновање стринга


не користе се други атомски типови података, па се, сходно неформалноj
дефинициjи наведеноj у уводноj секциjи овог поглавља, стринг може сма-
трати атомским типом података. С друге стране, у програмском jезику
Ц, стринг се представља као низ елемената чиjи тип података одгова-
ра засебном типу података намењеном представљању симбола, па се, у
складу с тим, стринг посматра као сложени тип података. Међутим, оно
што jе од суштинског значаjа, и заjедничко за оба становишта, jе да се
стринг користи за представљање симболичких података, тj., података у
форми текста. Разумевање природе одређеног типа података доприноси
томе да евентуалне — понекад само формалне — разлике у дефинисању
типова података не представљаjу сметњу програмеру у дизаjну и импле-
ментациjи програма у различитим програмским jезицима.

.
ић
Библиографскe напоменe:
ов

а.
• Префиксна нотациjа и рекурзивно израчунавање израза у про-
ат

ан
грамском jезику Ским описани су у секциjама „1.1.1 Expressions”
Гњ

ж
и „1.1.3 Evaluating Combinations” библиографског навода [1].

др
• Преглед атомских типова у програмском jезику Ракет дат jе у
ан

поглављу „1 Arithmetic” библиографског навода [5]. за


ил

су
М

а
1.

ав

1.8 Задаци
02

пр
–2

Задатак 1.1. Преведите следећи израз у префиксну форму:


а
20

Св

2 + 4 · ( 32 − (1 + 3))
20

.
2 + 4 · 32 − 1 + 3
а.
©

иj

Задатак 1.2. Коjе су вредности следећих израза?


рз

(а) (remainder (expt 4 2) (+ 2 1)),


ве

(б) (/ (∗ 3 (+ −1 2)) 4),


(в) ( string−append (substring "abcd" 2) (substring "abcd" 1 3)),
на

(г) (or (< (+ −2 3) (∗ −2 3)) (not (>= 3 2 3))).


д
Ра

Прикажите поступак израчунавања по корацима.

Задатак 1.3. Коjе су вредности следећих израза?


(а) (= (− 1 0.7) (− 0.7 0.4)),
(б) (= (− 1 0.7) (− (− 0.7 1))).
Обjасните. (Савет: в. пример 1.9.)
30 1 Атомски типови података

Задатак 1.4. У примеру 1.11 смо показали да се функциjа remainder


може применити за издваjање последње цифре целог броjа. Напишите
израз коjи издваjа последњу цифру целог броjа комбиновањем других
функциjа представљених у овом поглављу. (Савет: конвертуjте броj у
стринг.)

.
ић
ов

а.
ат

ан
Гњ

ж
др
ан

за
ил

су
М

а
1.

ав
02

пр
–2

а
20

Св
20

а.
©

иj
рз
ве
д на
Ра
Поглавље 2
Основни инструменти апстракциjе у
програмирању

.
ић
Сваки нетривиjални програм састоjи се од низа дефинициjа, иза коjег
ов
обично следи израз коjи укључуjе неке (или све) од претходно наведених

а.
дефинициjа. Под дефинициjама подразумевамо инструменте апстракци-
ат

ан
jе у програмирању. У овом поглављу ћемо се упознати с два основна
Гњ

ж
инструмента апстракциjе:

др
• дефинисањем променљивих, тj., додељивањем симболичких имена вред-
ан

ностима,
за
ил

• дефинисањем функциjа, тj., додељивањем симболичких имена опера-


су

циjама.
М

У наставку ћемо детаљниjе размотрити концепте глобалних и локалних


1.

ав

променљивих, функциjа и условног извршавања, функциjа вишег реда и


02

пр

безимених функциjа.
–2

а
20

Св
20

2.1 Глобалне променљиве


а.
©

иj

Jедан од основних аспеката програмирања односи се на додељивање


рз

симболичких имена вредностима, тj., на могућност да се некоj вредности


ве

приступи посредно, преко симболичког имена.


на

Пример 2.1. Командом:


( define a 2) , (2.1)
д
Ра

налажемо интерпретатору да симболичко име a повеже с вредношћу 2.


Након тога, можемо користити име a уместо вредности на коjе оно ука-
зуjе, што jе илустровано на сл. 2.1.
Симболичко име коjе jе додељено некоj вредности уобичаjено се нази-
ва променљивом. Из разлога коjи ће касниjе1 постати jасни, овде ћемо
1
В. 5. поглавље.

31
32 2 Основни инструменти апстракциjе у програмирању
 
> ( define a 2 )
> a
2
> (∗ 3 a )
6
> ( expt a 3)
8
 

Слика 2.1 Илустрациjа коришћења променљиве.

их посматрати као константе. У општем случаjу, синтаксичка структура


дефинициjе променљиве jе:

.
( define ime_promenljive izraz) , (2.2)
ић
ов

тj., симболичко име може се доделити вредности коjа представља резул-

а.
тат израчунавања произвољног, синтаксички исправног израза, укључу-
ат

ан
jући (али не ограничаваjући се на) изразе коjе смо разматрали у 1. по-
Гњ

ж
глављу.

др
Пример 2.2. Секвенцом команди приказаном на сл. 2.2, променљивоj a
ан

за
додељуjе се вредност 2, променљивоj b вредност 5, променљивоj c вред-
ил

ност #t, а променљивоj d вредност "ogr".


су
М

 
1.

ав

> ( define a (/ 8 4))


02

> ( define b (+ 3 a ) )
пр

> ( define c (< a b ) )


–2

> ( define d ( substring " p r o g r a m i r a n j e " a b ) )


а
20

> a
Св

2
20

> b
а.

5
©

иj

> c
#t
рз

> d
ве

" ogr "


 
на

Слика 2.2 Илустрациjа дефинисања глобалних променљивих.


д
Ра

Можемо приметити следеће:


• У подизразу за дефинисање вредности неке променљиве могу се кори-
стити друге, претходно дефинисане променљиве. У овом примеру, за
дефинисање вредности променљиве b коришћена jе променљива a, а за
дефинисање вредности променљивих c и d коришћене су променљиве
a и b.
2.2 Дефинисање функциjа 33

• Изрази коjи садрже променљиве израчунаваjу се на начин описан у 1.


поглављу, одоздо-нагоре, тj., у сваком кораку израчунаваjу се наjугне-
жђениjи делови израза.
• Синтаксичка структура дефинициjе променљиве (2.2) задовољава кри-
териjуме префиксног записа. Први елемент чини симбол define, други
елемент представља име променљиве, а трећи елемент jе израз чиjа се
вредност додељуjе имену променљиве.
• У општем случаjу, редослед дефинисања променљивих jе важан. Нпр.,
интерпретатору можемо саопштити следећу дефинициjу:

( define f (+ e 1)) , (2.3)

само ако jе променљива e претходно дефинисана2 . У супротном, ин-


терпретатор ће индиковати грешку, што jе илустровано на сл. 2.3.
.
ић
 
ов

а.
> ( define f (+ e 1 ) )
ат

. . . e : undefined ;

ан
ca nn ot r e f e r e n c e an i d e n t i f i e r b e f o r e i t s definition
Гњ

 

ж
др
Слика 2.3 Индиковање грешке изазване референцирањем недефинисане променљи-
ан

ве.
за
ил

су
М

Могућност додељивања симболичког имена некоj вредности захтева


а
1.

ав

постоjање мемориjе у коjоj се памте везе између симболичких имена и


02

додељених вредности. Ова мемориjа назива се глобалним окружењем, а


пр

овакве променљиве — глобалним променљивама.


–2

Програмери имаjу релативно висок степен слободе при изабирању сим-


а
20

Св

боличког имена променљиве, иако су, у извесноj мери, ограничени син-


20

таксичким правилима конкретног програмског jезика. Добра пракса jе да


а.

име променљиве буде индикативно у односу на њену улогу у контексту


©

иj

датог програма.
рз
ве

2.2 Дефинисање функциjа


д на

Симболичка имена могу се додељивати и сложеним операциjама, коjе


Ра

уобичаjено називамо функциjама.

Пример 2.3. Посматраjмо следећи пример математичке функциjе:


2
Прецизниjе формулисано, да би интерпретатор прихватио дефинициjу (2.3), потреб-
но jе да буду задовољена два услова: (i) променљива e мора бити претходно дефини-
сана, и (ii) вредност додељена променљивоj e мора бити таква да може да се саопшти
оператору + као улазни аргумент.
34 2 Основни инструменти апстракциjе у програмирању

f1 (x) = x2 , x ∈ C , (2.4)

коjа прихвата комплексни броj x као улазни аргумент, и враћа вредност


коjа се израчунава по формули x2 . Еквивалентна функциjа, написана
на програмском jезику Ракет, приказана jе на сл. 2.4, њена синтаксич-
ка структура разложена jе на сл. 2.5, а примена илустрована на сл. 2.6.
Ако се у команди саопштеноj интерпретатору наведе само име функциjе,
без прослеђивања вредности улазног аргумента x (в. прву команду на сл.
2.6), интерпретатор обавештава да симболичко име f1 представља функ-
циjу, али jе не извршава. Ако функциjи саопштимо броj, интерпретатор
израчунава и приказуjе њену вредност за дати улазни аргумент (в. другу,
трећу и четврту команду на сл. 2.6). Слично као променљиве, функциjе
се могу позивати у изразима (в. последњу команду на сл. 2.6).

.
ић
1 ( define ( f 1 x ) ( ∗ x x ) )
ов

а.
ат

ан
Слика 2.4 Функциjа коjа прихвата броj x као улазни аргумент, и израчунава вред-
Гњ

ж
ност x2 .

др
ан

за
ил

Слика 2.5 Синтаксичка ( define ( f1 x ) (* x x) )


су

структура дефинициjе
М

функциjе дате на сл. 2.4. дефиниши функциjу f1


а

коjа прихвата аргумент x


1.

ав

и израчунава вредност x2
02

пр
–2

а
20

Св

 
20

> f1
а.

#<procedure : f1>
©

> ( f1 2)
иj

4
рз

> ( f 1 −1 . 5 )
2.25
ве

> ( f 1 1+2 i )
−3+4 i
на

> (− ( f 1 3 ) ( f 1 2 ) )
д

5
 
Ра

Слика 2.6 Резултати позивања функциjе дефинисане на сл. 2.4 кад jоj се саопште
изабрани улазни аргументи.
2.2 Дефинисање функциjа 35

У општем случаjу, синтаксичка структура дефинициjе функциjе jе3 :

( define (ime−funkcije niz−ulaznih−argumenata) izraz) . (2.5)

Први елемент овог израза чини симбол define, други елемент чине име
функциjе и низ улазних аргумената, а трећи елемент jе подизраз коjи
представља поступак израчунавања вредности функциjе, и уобичаjено
се назива телом функциjе.

Пример 2.4. Дефинишимо функциjу коjа прихвата броj x и израчунава


вредност 5x2 + 2x + 1.
Дефинициjа ове функциjе дата jе на сл. 2.7, a њено извршавање илу-
стровано jе на сл. 2.8.

.
ић
1 ( define ( polinom x )
ов
2 (+ ( ∗ 5 x x )

а.
3 (∗ 2 x )
ат

ан
4 1))
Гњ

ж
др
Слика 2.7 Дефинициja функциje f (x) = 5x2 + 2x + 1.
ан

за
ил

су

 
М

> ( polinom 1 )
а
1.

ав

8
> ( polinom 1 . 5 )
02

пр

15.25
–2

> ( polinom 3 − 2i )
а

32 − 64i
20

 
Св
20

Слика 2.8 Илустрациjа извршавања функциjе дефинисане на сл. 2.7.


а.
©

иj
рз

Пример 2.5. Дефинишимо функциjу коjа израчунава запремину коцке,


ве

при чему улазни аргумент ове функциjе представља дужину странице


коцке.
на

Дефинициjа функциjе дата jе на сл. 2.9, a њено извршавање илустро-


д

вано jе на сл. 2.10.


Ра

Ову jедноставну функциjу ћемо искористити да укажемо на важност


провере валидности улазних аргумената. Улазни аргумент a представља
дужину странице коцке, па jе функциjа дизаjнирана под имплицитном

3
Приметимо да синтаксичка структура дефинициjе функциjе задовољава критериjу-
ме префиксног записа.
36 2 Основни инструменти апстракциjе у програмирању

1 ( define ( zapremina a ) ( e x p t a 3 ) )

Слика 2.9 Дефинициja функциje коjа израчунава запремину коцке.


 
> ( zapremina 1 . 5 )
3.375
> ( zapremina −1 . 5 )
−3 . 3 7 5
> ( zapremina 3 − 2i )
− 9 − 46i
> ( zapremina " kocka " )
. . . expt : c o n t r a c t v i o l a t i o n
e x p e c t e d : number?
g i v e n : " kocka "
argument p o s i t i o n : 1 s t
.
ић
o t h e r arguments . . . :
 
ов

а.
ат

Слика 2.10 Илустрациjа извршавања функциjе дефинисане на сл. 2.9.

ан
Гњ

ж
др
претпоставком да jе a позитивни реални броj4 . У складу с тим, функци-
ан

jа генерише очекиване резултате у случаjевима кад jе ова претпоставка


за
задовољена. Међутим, корисник коjи саопштава улазни аргумент овоj
ил

су
функциjи нема обавезу да задовољи претпоставку коjу jе увео програ-
М

мер. Нпр., ако се функциjи саопшти стринг уместо броjа, индикуjе се


а

грешка, а извршавање програма се прекида. Jош критичниjи jе случаj


1.

ав

кад се функциjи саопшти комплексни или негативни броj, jер тад функ-
02

пр

циjа генерише неодговараjући резултат (нпр., негативну запремину), али


–2

се извршавање програма наставља, што може да доведе до неочекиваног


а
20

понашања делова програма коjи користе повратну вредност функциjе,


Св

укључуjући и нарушавање сигурности програма. Због тога, обавеза про-


20

грамера jе да провери валидност улазних аргумената (jедан од начина за


а.
©

проверу валидности улазних аргумената размотрен jе у примеру 2.11).


иj

У овоj књизи, већину функциjа ћемо дефинисати под претпоставком


рз

да су вредности улазних аргумената валидне, да не бисмо изложене


ве

програмске кодове оптерећивали проверама коjе немаjу директне везе


с основним дизаjном функциjе. Ипак, читалац треба да буде свестан ва-
на

жности провере валидности улазних података у практичним применама.


д
Ра

Пример 2.6. Дефинишимо функциjу коjа прихвата два цела броjа, и


утврђуjе да ли jе први броj дељив другим.

4
Формално представљено, дефинициjа дата на сл. 2.9 имплементира функциjу f (a) =
a3 , a ∈ C, а требало би да имплементира функциjу f (a) = a3 , a ∈ R+ .
2.2 Дефинисање функциjа 37

Дефинициjа ове функциjе5 дата jе на сл. 2.11, a њено извршавање


илустровано jе на сл. 2.12. Функциjа враћа вредност #t ако jе први ула-
зни аргумент x дељив другим улазним аргументом y, а вредност #f у
супротном.

1 ( define ( d e l j i v ? x y )
2 ( and ( not (= y 0 ) )
3 (= ( r e m a i n d e r x y ) 0 ) ) )

Слика 2.11 Дефинициja функциje коjа проверава дељивост jедног целог броjа дру-
гим целим броjем.

.
ић
 
ов
> ( d e l j i v ? 9 3)

а.
#t
ат

ан
> ( d e l j i v ? 9 4)
Гњ

#f

ж
> ( d e l j i v ? 9 0)

др
#f
 
ан

за
ил

Слика 2.12 Илустрациjа извршавања функциjе дефинисане на сл. 2.11.


су
М

Анализираjмо израз коjи чини тело ове функциjе. Броj x дељив jе


1.

ав

броjем y ако и само ако jе остатак целоброjног дељења x с y jеднак нули.


02

пр

Оваj услов могао би се записати на следећи начин:


–2

а
20

(= (remainder x y) 0) . (2.6)
Св
20

Међутим, ако jе вредност аргумента y jеднака нули, израчунавање израза


а.
©

(2.6) изазива грешку у извршавању програма, jер дељење нулом ниjе


иj

дозвољено. Jедан начин да превазиђемо оваj проблем jе да проширимо


рз

израз (2.6) на следећи начин:


ве

(and (not (= y 0)) (= (remainder x y) 0)) . (2.7)


на

Конкретни интерпретатор, коришћен за имплементирање и тестирање


д

овог изворног ко̂да, израчунава израз (2.7) слева-надесно. Ако важи y = 0,


Ра

вредност првог елемента конjункциjе — (not (= y 0)) — jеднака jе #f, из


чега следи да jе вредност целог израза jеднака #f, па се други елемент
конjункциjе — (= (remainder x y) 0) — не израчунава, тj., не покушава

5
Следећи конвенциjу именовања предиката (в. секциjу 1.4.1, у 1. поглављу), назив
ове функциjе завршава се знаком питања. Ова конвенциjа именовања функциjа ниjе
обавезна.
38 2 Основни инструменти апстракциjе у програмирању

се дељење нулом. У супротном, ако важи y 6= 0, вредност првог елемента


конjункциjе jеднака jе #t, па jе вредност целог израза одређена вред-
ношћу другог елемента конjункциjе. У складу с тим, редослед навођења
елемената у изразу (2.7) jе важан, за разлику од математике, где jе опера-
циjа конjункциjе комутативна. Да jе тело функциjе чинио следећи израз:

(and (= (remainder x y) 0) (not (= y 0))) , (2.8)

увек би се прво израчунавао подизраз (= (remainder x y) 0), чиме би гре-


шка узрокована покушаjем дељења нулом и даље била актуелна.
Коначно, треба приметити да jе решење на сл. 2.11 изложено због
педагошких разлога, али да не представља пример добре програмерске
праксе, jер се ослања на претпоставку одређеног редоследа израчуна-
вања делова израза на истом хиjерархиjском нивоу. У примеру 1.3 (в.
.
ић
1. поглавље) истакнуто jе да не треба писати програме чиjи резултат
извршавања зависи од специфичних дизаjнерских аспеката конкретних
ов

а.
интерпретатора и преводилаца. Дефинициjа функциjе deljiv ?, коjа jе у
ат

ан
складу с овом препоруком, дата jе у примеру 2.10.
Гњ

ж
Пример 2.7. Дефинишимо функциjу коjа проверава да ли jе дата година

др
преступна. Преступна година jе дељива броjем 4, а ако jе дељива броjем
ан

100, мора бити дељива и броjем 400.


за
ил

Тражену функциjу можемо дефинисати тако да скуп њених повратних


су

вредности садржи само два елемента: #t, ако jе година преступна, одно-
М

сно #f, у супротном. Из поставке примера следи да буловски израз коjи


а

генерише повратну вредност узима у обзир само jедан улазни аргумент


1.

ав

— годину. Да бисмо лакше представили поступак формирања буловског


02

пр

израза, користићемо следеће променљиве. Нека g представља годину, а


–2

p, q и r буловске вредности коjе су дефинисане на следећи начин:


а
20

Св

• вредност p jеднака jе #t, ако jе g дељиво броjем 4, односно #f, у


20

супротном,
а.
©

• вредност q jеднака jе #t, ако jе g дељиво броjем 100, односно #f, у


иj

супротном,
рз

• вредност r jеднака jе #t, ако jе g дељиво броjем 400, односно #f, у


супротном.
ве

Услов за преступност године, дат у поставци примера, може се записати:


д на

p ∧ (q ⇒ r) , (2.9)
Ра

а потом и трансформисати6 тако да се елиминише операциjа имплика-


циjе:
p ∧ (¬q ∨ r) . (2.10)

6
Овде примењуjемо таутологиjу: (q ⇒ r) ⇔ (¬q ∨ r)
2.2 Дефинисање функциjа 39

Буловски израз (2.10) можемо директно пресликати у тело функциjе


дате на сл. 2.13. У телу ове функциjе позива се функциjа deljiv ?, прет-
ходно дефинисана на сл. 2.11. Тиме jе дефинициjа функциjе учињена
читљивиjом, што се може уочити кад ову дефинициjу упоредимо с дефи-
нициjом датом на сл. 2.14, коjа такође имплементира израз (2.10), али
не позива функциjу deljiv ?, већ садржи изразе коjи одговараjу телу ове
функциjе. Приметимо да би разлика у сложености записа дефинициjа
функциjа на сл. 2.13 и 2.14 била jош значаjниjа да jе функциjа deljiv ?
синтаксички или садржаjно сложениjа.

1 ( define ( p r e s t u p n a ? g o d i n a )
2 ( and
3 ( d e l j i v ? godina 4)
4 ( or
.
ић
5 ( not ( d e l j i v ? g o d i n a 1 0 0 ) )
ов
6 ( d e l j i v ? godina 4 0 0 ) ) ) )

а.
ат

ан
Слика 2.13 Дефинициja функциje коjа проверава да ли jе година преступна.
Гњ

ж
др
ан

за
ил

1 ( define ( p r e s t u p n a ? g o d i n a )
су

2 ( and
М

3 (= ( r e m a i n d e r g o d i n a 4 ) 0 )
а

4 ( or
1.

ав

5 ( not (= ( r e m a i n d e r g o d i n a 1 0 0 ) 0 ) )
02

пр

6 (= ( r e m a i n d e r g o d i n a 4 0 0 ) 0 ) ) ) )
–2

а
20

Слика 2.14 Друга дефинициja функциje коjа проверава да ли jе година преступна.


Св
20

а.
©

У општем случаjу, за дати информатички проблем постоjи више од


иj

jедног програмског решења, при чему jе избор оптималног решења усло-


рз

вљен контекстом примене датог програма. Да бисмо то илустровали, раз-


мотрићемо jош jедно решење проблема утврђивања преступности године.
ве

Кад се на израз (2.10) примени дистрибутивни закон, добиjа се:


на

(p ∧ ¬q) ∨ (p ∧ r) . (2.11)
д
Ра

Посматраjмо другу компоненту горњег израза: (p ∧ r). Из дефинициjа p


и r следи да ако jе вредност r jеднака #t (тj., ако jе g дељиво броjем 400),
онда и вредност p мора бити jеднака #t (тj., g мора бити дељиво броjем
4). Другим речима, r представља „строжиjи” услов од p, тако да jе (p ∧
r), у ствари, еквивалентно r, а израз (2.11) последично jе еквивалентан
следећем изразу:
(p ∧ ¬q) ∨ r , (2.12)
40 2 Основни инструменти апстракциjе у програмирању

на основу кога jе дефинисана функциjа приказана на сл. 2.15.

1 ( define ( p r e s t u p n a ? g o d i n a )
2 ( or
3 ( and
4 ( d e l j i v ? godina 4)
5 ( not ( d e l j i v ? g o d i n a 1 0 0 ) ) )
6 ( d e l j i v ? godina 4 0 0 ) ) )

Слика 2.15 Трећа дефинициja функциje коjа проверава да ли jе година преступна.

Извршавање функциjа дефинисаних на сл. 2.13, 2.14 и 2.15 илустро-


вано jе на сл. 2.16.
.
ић
 
ов

а.
> ( prestupna? 1900)
ат

#f

ан
> ( prestupna? 2000)
Гњ

ж
#t
 

др
ан

за
Слика 2.16 Илустрациjа извршавања функциjа дефинисаних на сл. 2.13, 2.14 и 2.15.
ил

су
М

а
1.

ав
02

2.3 Условно извршавање


пр
–2

Синтаксичка структура израза за условно извршавање jе:


20

Св
20

( if bulovski−izraz izraz1 izraz2 ) , (2.13)


а.
©

иj

а вредност израза израчунава се на следећи начин:


рз

• Ако jе вредност израза bulovski−izraz jеднака #t, вредност израза


(2.13) jеднака jе вредности израза izraz1.
ве

• У супротном, вредност израза (2.13) jеднака jе вредности израза


на

izraz2.
д

.
Ра

Пример 2.8. Дефинишимо функциjу коjа прихвата два броjа, и као ре-
зултат враћа већи од њих, тj.:

f (a, b) = max{a, b}, за a, b ∈ C . (2.14)

Основна дефинициjа ове функциjе дата jе на сл. 2.17. Тело функциjе


чини израз за условно извршавање у коjем се посматра услов a > b. Ако
2.3 Условно извршавање 41

jе услов задовољен, тj., ако jе a већe од b, вредност израза jеднака jе a.


У супротном, ако jе a мање од или jеднако b, вредност израза jеднака jе
b.

1 ( define ( maks2 a b )
2 ( i f (> a b ) a b ) )

Слика 2.17 Дефинициja функциje коjа прихвата два реална броjа, и као резултат
враћа већи од њих.

Резултати позивања ове функциjе кад jоj се саопште изабрани улазни


аргументи приказани су на сл. 2.18, а детаљниjи приказ израчунавања
.
резултата дат jе на сл. 2.19. Функциjа генерише очекиване резултате кад
ић
jоj се саопште реални броjеви, али индикуjе грешку кад jоj се саопшти
ов

(бар jедан) комплексни броj. Ово ниjе неочекивано, jер се оператор >

а.
ат

не може применити над комплексним броjевима (в. пример 1.15, у 1.

ан
поглављу).
Гњ

ж
др
 
ан

> ( maks2 3 4 )
за
4
ил

су
> ( maks2 −5 . 5 −6 . 2 )
М

−5 . 5
> ( maks2 4 4 )
а
1.

ав

4
> ( maks2 −5 −6+2 i )
02

пр

. . . >: c o n t r a c t v i o l a t i o n
–2

expected : r e a l ?
а

g i v e n : −6+2 i
20

Св

argument p o s i t i o n : 2nd
20

o t h e r arguments . . . :
 
а.
©

иj

Слика 2.18 Илустрациjа извршавања функциjе дефинисане на сл. 2.17.


рз
ве

Претпоставимо да желимо да функциjа прихвата и комплексне броjеве


као улазне аргументе. Тада jе потребно да одредимо правило по коjем се
на

неки комплексни броj c1 може сматрати већим од другог комплексног


д

броjа c2 . Илустрациjе ради7 , усвоjимо правило да jе c1 веће од c2 :


Ра

• ако jе реални део броjа c1 већи од реалног дела броjа c2 , или


• ако су им реални делови jеднаки, и имагинарни део броjа c1 већи од
имагинарног дела броjа c2 ,

7
Правило за поређење комплексних броjева ниjе математички утемељено, и овде га
усваjамо само за потребе илустровања примене израза за условно извршавање.
42 2 Основни инструменти апстракциjе у програмирању

( maks2 3 4 )
( i f (> 3 4 ) 3 4 )
( i f #f 3 4 )
4

( maks2 −5 . 5 −6 . 2 )
( i f (> −5 . 5 −6 . 2 ) −5 . 5 −6 . 2 )
( i f #t −5.5 −6 . 2 )
−5.5

( maks2 4 4 )
( i f (> 4 4 ) 4 4 )
( i f #f 4 4 )
4

( maks2 −5 −6+2 i )
.
ић
( i f ( > −5 − 6 + 2i ) −5 −6+2 i )
... >: c o n t r a c t v i o l a t i o n ...
ов

а.
ат

ан
Слика 2.19 Приказ извршавања функциjе дефинисане на сл. 2.17 кад jоj се саопште
Гњ

ж
изабрани улазни аргументи.

др
ан

тj.:
за
ил

су

c1 > c2 ⇔ (Re(c1 ) > Re(c2 )) ∨ ((Re(c1 ) = Re(c2 )) ∧ (Im(c1 ) > Im(c2 ))) , (2.15)
М

где су Re(c) и Im(c), респективно, реални и имагинарни делови комплек-


1.

ав

сног броjа c. Дефинициjа функциjе коjа пореди комплексне броjеве по


02

пр

датом правилу приказана jе на сл. 2.20, њено извршавање илустровано


–2

jе на сл. 2.21, а детаљниjи приказ израчунавања резултата дат jе на сл.


а
20

2.22. Треба приметити да функциjе дате на сл. 2.17 и 2.20 генеришу исте
Св

резултате кад им се саопште реални улазни аргументи, и да разлике у


20

њиховом израчунавању постаjу видљиве тек кад им се саопшти бар jедан


а.
©

комплексни броj.
иj
рз
ве

1 ( define ( maks2−komp a b )
2 ( i f ( or (> ( r e a l − p a r t a ) ( r e a l − p a r t b ) )
на

3 ( and (= ( r e a l − p a r t a ) ( r e a l − p a r t b ) )
4 (> ( imag − part a ) ( imag − part b ) ) ) )
д

5 a b))
Ра

Слика 2.20 Дефинициja функциje коjа прихвата два комплексна броjа, и као резул-
тат враћа „већи” од њих.

Пример 2.9. Дефинишимо функциjу коjа прихвата три реална броjа, и


као резултат враћа наjвећи од њих, тj.:
2.3 Условно извршавање 43
 
> ( maks2−komp 3 4)
4
> ( maks2−komp −5 . 5 −6 . 2 )
−5 . 5
> ( maks2−komp −5 −6+2 i )
−5
> ( maks2−komp −6+1 i −6+2 i )
−6+2 i
> ( maks2−komp 1+2 i 1+2 i )
1+2 i
 

Слика 2.21 Илустрациjа извршавања функциjе дефинисане на сл. 2.20.


 
( maks2−komp 3 4 )

.
( i f ( or (> ( r e a l − p a r t 3 ) ( r e a l − p a r t 4 ) )
ић
( and (= ( r e a l − p a r t 3 ) ( r e a l − p a r t 4 ) )
(> ( imag − part 3 ) ( imag − part 4 ) ) ) )
ов

а.
3 4)
ат

ан
( i f ( or (> 3 4 ) ( and (= 3 4 ) (> 0 0 ) ) ) 3 4 )
( i f ( or #f ( and #f #f ) ) 3 4 )
Гњ

ж
( i f #f 3 4 )

др
4
ан

( maks2−komp −5 −6+2 i )
за
ил

( i f ( or (> ( r e a l − p a r t −5) ( r e a l − p a r t −6+2 i ) )


су

( and (= ( r e a l − p a r t −5) ( r e a l − p a r t −6+2 i ) )


М

(> ( imag − part −5) ( imag − part −6+2 i ) ) ) )


а

−5 −6+2 i )
1.

ав

( i f ( or (> −5 −6) ( and (= 5 −6) (> 0 2 ) ) ) −5 −6+2 i )


02

( i f ( or #t ( and #f #f ) ) −5 −6+2 i )
пр

( i f #t −5 −6+2 i )
–2

−5
а
20

Св

( maks2−komp −6+1 i −6+2 i )


20

( i f ( or (> ( r e a l − p a r t −6+1 i ) ( r e a l − p a r t −6+2 i ) )


а.
©

( and (= ( r e a l − p a r t −6+1 i ) ( r e a l − p a r t −6+2 i ) )


иj

(> ( imag − part −6+1 i ) ( imag − part −6+2 i ) ) ) )


−6+1 i −6+2 i )
рз

( i f ( or (> −6 −6) ( and (= −6 −6) (> 1 2 ) ) ) −6+1 i −6+2 i )


ве

( i f ( or #f ( and #t #f ) ) −6+1 i −6+2 i )


( i f #f −6+1 i −6+2 i )
на

−6+2 i
 
д
Ра

Слика 2.22 Приказ извршавања функциjе дефинисане на сл. 2.20 кад jоj се саопште
изабрани улазни аргументи.
44 2 Основни инструменти апстракциjе у програмирању

f (a, b, c) = max{a, b, c}, за a, b, c ∈ R . (2.16)

Jедна од могућих дефинициjа ове функциjе дата jе на сл. 2.23. Тело


функциjе чини израз за условно извршавање коjи садржи два угнежђена
израза за условно извршавање, и може се интерпретирати на следећи
начин. Прво се пореде вредности аргумената a и b. Ако важи a > b, то
значи да вредност b сигурно ниjе максимална, па се у наредном кораку
пореде вредности аргумената a и c, а као резултат се враћа већа вредност.
Ако не важи a > b, то значи да вредност a можемо да искључимо из
поређења, па се у наредном кораку пореде вредности аргумената b и c, а
као резултат се враћа већа вредност.

1 ( define ( maks3 a b c )
2 ( i f (> a b )
.
ић
3 ( i f (> a c ) a c )
ов
4 ( i f (> b c ) b c ) ) )

а.
ат

ан
Слика 2.23 Дефинициja функциje коjа прихвата три реална броjа, и као резултат
Гњ

ж
враћа наjвећи од њих.

др
ан

за
Резултати позивања ове функциjе кад jоj се саопште изабрани улазни
ил

аргументи приказани су на сл. 2.24, а детаљниjи приказ израчунавања


су
М

резултата дат jе на сл. 2.25.


а
1.

ав

 
02

пр

> ( maks3 1 . 1 2 3 . 5 )
3.5
–2

> ( maks3 3 . 5 1 . 1 2 )
а
20

Св

3.5
> ( maks3 2 3 . 5 1 . 1 )
20

3.5
а.

 
©

иj

Слика 2.24 Илустрациjа извршавања функциja дефинисаних на сл. 2.23 и 2.26.


рз
ве

Други начин да се дефинише тражена функциjа приказан jе на сл.


на

2.26. У овоj дефинициjи позива се функциjа maks2 (претходно дефини-


сана8 у примеру 2.8), коjа прихвата два броjа, и као резултат враћа већи
д
Ра

од њих. У првом позиву, функциjи maks2 саопштаваjу се аргументи b


и c. Резултат овог позива саопштава се — заjедно с вредношћу a — као
улазни аргумент у другом позиву исте функциjе.

8
У примеру 2.8 дате су две дефинициjе функциjе maks2, на сл. 2.17 и 2.20. Пошто
обе верзиjе функциjе генеришу исте резултате кад им се саопште реални улазни ар-
гументи, свеjедно jе коjу од њих позивамо у овом примеру.
2.3 Условно извршавање 45

( maks3 1.1 2 3.5)


( i f (> 1 . 1 2 ) ( i f (> 1 . 1 3 . 5 ) 1 . 1 3 . 5 ) ( i f (> 2 3 . 5 ) 2 3 . 5 ) )
( i f #f ( i f (> 1 . 1 3 . 5 ) 1 . 1 3 . 5 ) ( i f (> 2 3 . 5 ) 2 3 . 5 ) )
( i f (> 2 3.5) 2 3.5)
( i f #f 2 3.5)
3.5

( maks3 3.5 1.1 2)


( i f (> 3.5 1 . 1 ) ( i f (> 3 . 5 2 ) 3 . 5 2 ) ( i f (> 1 . 1 2 ) 1 . 1 2 ) )
( i f #t ( if (> 3 . 5 2 ) 3 . 5 2 ) ( i f (> 1 . 1 2 ) 1 . 1 2 ) )
( i f (> 3.5 2) 3.5 2)
( i f #t 3.5 2)
3.5

( maks3 2 3.5 1.1)


( i f (> 2 3 . 5 ) ( i f (> 2 1 . 1 ) 2 1 . 1 ) ( i f (> 3 . 5 1 . 1 ) 3 . 5 1 . 1 ) )
.
ић
( i f #f ( i f (> 2 1 . 1 ) 2 1 . 1 ) ( i f (> 3 . 5 1 . 1 ) 3 . 5 1 . 1 ) )
( i f (> 3.5 1.1) 3.5 1.1)
ов
( i f #t 3.5 1.1)

а.
3.5
ат

ан
Гњ

ж
Слика 2.25 Приказ извршавања функциjе дефинисане на сл. 2.23 кад jоj се саопште

др
изабрани улазни аргументи.
ан

за
ил

Резултати позивања функциjе maks3, дефинисане на сл. 2.26, прика-


су
М

зани9 су на сл. 2.24, а детаљниjи приказ израчунавања резултата дат jе


а

на сл. 2.27.
1.

ав
02

пр

1 ( define ( maks3 a b c )
–2

2 ( maks2 a ( maks2 b c ) ) )
а
20

Св
20

Слика 2.26 Друга дефинициja функциje коjа прихвата три реална броjа, и као ре-
а.
©

зултат враћа наjвећи од њих.


иj
рз
ве

Пример 2.10. Посматраjмо опет проблем дефинисања функциjе коjа при-


хвата два цела броjа, и проверава да ли jе први броj дељив другим.
на

Решење овог проблема дато у примеру 2.6 имало jе недостатак: функ-


д

циjа приказана на сл. 2.11 дефинисана je под претпоставком да се делови


Ра

израза на истом хиjерархиjском нивоу израчунаваjу слева-надесно. Упо-


требом израза за условно извршавање можемо да дефинишемо функциjу
(в. сл. 2.28) коjа решава дати проблем, и чиjи резултат извршавања не
зависи од редоследа израчунавања подизраза на истом хиjерархиjском
9
Две верзиjе функциjе maks3, дефинисане на сл. 2.23 и 2.26, враћаjу исте резулта-
те за исте троjке улазних реалних аргумената, па су резултати њихових позивања
приказани на истоj слици (тj., сл. 2.24).
46 2 Основни инструменти апстракциjе у програмирању

( maks3 1 . 1 2 3 . 5 )
( maks2 1 . 1 ( maks2 2 3 . 5 ) )
( maks2 1 . 1 3 . 5 )
3.5

( maks3 3 . 5 1 . 1 2 )
( maks2 3 . 5 ( maks2 1 . 1 2 ) )
( maks2 3 . 5 2 )
3.5

( maks3 2 3 . 5 1 . 1 )
( maks2 2 ( maks2 3 . 5 1 . 1 ) )
( maks2 2 3 . 5 )
3.5

.
Слика 2.27 Приказ извршавања функциjе дефинисане на сл. 2.26 кад jоj се саопште
ић
изабрани улазни аргументи.
ов

а.
ат

ан
нивоу. Ова функциjа прво проверава да ли jе вредност аргумента y jед-
Гњ

ж
нака нули. Ако jесте, враћа се резултат #f. У супротном, проверава се

др
услов (2.6).
ан

за
ил

1 ( define ( d e l j i v ? x y )
су
М

2 ( i f (= y 0 )
3 #f
а
1.

4 (= ( r e m a i n d e r x y ) 0 ) ) )
ав
02

пр
–2

Слика 2.28 Друга дефинициja функциje коjа проверава дељивост jедног целог броjа
другим целим броjем.
а
20

Св
20

а.
©

Пример 2.11. Посматраjмо опет проблем дефинисања функциjе коjа из-


иj

рачунава запремину коцке, при чему улазни аргумент ове функциjе пред-
рз

ставља дужину странице коцке.


У примеру 2.5 истакнуто jе да функциjа дефинисана на сл. 2.9 имa
ве

недостатак: ако се овоj функциjи саопшти вредност коjа ниjе позитивни


на

реални броj, индикуjе се грешка или се генерише неодговараjући резултат


(нпр., негативна запремина). У овом примеру размотрићемо jедан начин
д
Ра

за проверу валидности улазних аргумената. Нова дефинициjа функциjе


дата jе на сл. 2.29. Ова функциjа прво проверава да ли jе улазни аргу-
мент a реални броj (применом предиката real?). Ако ниjе, генерише се
вредност 0. У супротном, ако a jесте реални броj, у угнежђеном изразу
за условно извршавање проверава се да ли jе a позитивни броj. Ако jе-
сте, израчунава се запремина, а у супротном се генерише вредност 0 (в.
задатак 2.1). Извршавање функциjе илустровано jе на сл. 2.30.
2.3 Условно извршавање 47

1 ( define ( zapremina a )
2 ( if ( real? a)
3 ( i f (> a 0 )
4 ( expt a 3)
5 0)
6 0))

Слика 2.29 Друга дефинициja функциje коjа израчунава запремину коцке.


 
> ( zapremina 1.5)
3.375
> ( zapremina −1 . 5 )
0
> ( zapremina 3 − 2i )
0
.
ић
> ( zapremina " kocka " )
0
ов

 

а.
ат

ан
Слика 2.30 Илустрациjа извршавања функциjе дефинисане на сл. 2.29.
Гњ

ж
др
ан

2.3.1 Вишеструко гранање тока извршавања за


програма
ил

су
М

Угнежђавањем израза за условно извршавање може се имплементи-


а
1.

рати вишеструко гранање тока извршавања програма. Посматраjмо, као


ав

наjпростиjи пример, синтаксичку структуру угнежђеног израза за услов-


02

пр

но извршавање приказану на сл. 2.31. Изрази овакве синтаксичке струк-


–2

туре израчунаваjу се на следећи начин:


а
20

Св

1. Прво се израчунава вредност подизраза bulovski−izraz−1. Ако jе вред-


20

ност овог подизраза jеднака #t, израчунава се вредност подизраза


а.
©

izraz−1, коjа представља коначни резултат израчунавања (тj., наред-


иj

ни кораци се не извршаваjу). У супротном, ако jе вредност подизраза


рз

bulovski−izraz−1 jеднака #f, прелази се на 2. корак.


ве

2. Израчунава се вредност израза bulovski−izraz−2. Ако jе вредност овог


подизраза jеднака #t, израчунава се вредност подизраза izraz−2, коjа
на

представља коначни резултат израчунавања (тj., 3. корак се не извр-


шава). У супротном, ако jе вредност подизраза bulovski−izraz−2 jед-
д
Ра

нака #f, прелази се на 3. корак.


3. Израчунава се вредност подизраза izraz−3, коjа представља коначни
резултат израчунавања.
Оваj поступак израчунавања може се алтернативно представити изра-
зом за вишеструко гранање тока извршавања програма чиjа jе синтак-
сичка структура дата на сл. 2.32.
48 2 Основни инструменти апстракциjе у програмирању
 
( i f bulovski−izraz−1
izraz−1
( i f bulovski−izraz−2
izraz−2
izraz−3 ) )
 

Слика 2.31 Синтаксичка структура угнежђеног израза за условно извршавање.


 
( cond
[ bulovski−izraz−1 izraz−1 ]
[ bulovski−izraz−2 izraz−2 ]
[ else izraz−3 ] )
 

.
Слика 2.32 Синтаксичка структура израза за вишеструко гранање тока извршавања
ић
програма коjи представља исти поступак израчунавања као израз 2.31.
ов

а.
ат

ан
Пример 2.12. Функциjа представљена на сл. 2.29 може се алтернативно
Гњ

дефинисати применом израза за вишеструко гранање, што jе приказано

ж
на сл. 2.33.

др
ан

за
ил

1 ( define ( zapremina a )
су

2 ( cond
М

3 [ ( not ( r e a l ? a ) ) 0 ]
а

4 [ (> a 0 ) ( e x p t a 3 ) ]
1.

ав

5 [ else 0 ] ) )
02

пр
–2

Слика 2.33 Трећа дефинициja функциje коjа израчунава запремину коцке.


а
20

Св
20

а.

У општем случаjу, синтаксичка структура израза за вишеструко гра-


©

иj

нање тока извршавања програма приказана jе на сл. 2.34, a израчунавање


рз

оваквих израза врши се на следећи начин:


ве

• Вредности подизраза у низу


на

bulovski−izraz−1, bulovski−izraz−2, . . . , bulovski−izraz−n (2.17)


д
Ра

израчунаваjу се у редоследу навођења, све док се не наиђе на први


подизраз чиjа jе вредност jеднака #t, или на краj низа.
• Ако jе у низу (2.17) детектован подизраз

bulovski−izraz−i, где jе: 1 ≤ i ≤ n , (2.18)


2.3 Условно извршавање 49

чиjа jе вредност jеднака10 #t, израчунава се подизраз izraz−i, и ње-


гова вредност представља коначну вредност израза датог на сл. 2.34.
• У супротном, ако у низу (2.17) не постоjи подизраз чиjа jе вредност
jеднака #t, израчунава се подизраз izraz−0, и његова вредност пред-
ставља коначну вредност израза датог на сл. 2.34.
• Навођење дела израза [ else izraz−0] jе опционо. Aко се оваj део из-
остави, и ако су вредности свих подизраза у низу (2.17) jеднаке #f,
израз дат на сл. 2.34 не генерише вредност.

 
( cond
[ bulovski−izraz−1 izraz−1 ]
[ bulovski−izraz−2 izraz−2 ]
...
.
ић
[ bulovski−izraz−n izraz−n ]
[ else izraz−0 ] )
ов
 

а.
ат

ан
Слика 2.34 Синтаксичка структура израза за условно извршавање, у општем слу-
Гњ

ж
чаjу.

др
ан

за
Пример 2.13. Дефинишимо функциjу коjа прихвата jедан аргумент, и
ил

су
враћа стринг чиjи садржаj индикуjе скуп броjева коjем припада улазни
М

аргумент.
а

Дефинициjа функциjе приказана jе на сл. 2.35, а њено извршавање


1.

ав

илустровано jе на сл. 2.36.


02

пр
–2

1 ( define ( v r s t a − b r o j a x )
20

Св

2 ( cond
20

3 [ ( integer? x) " c e l i broj "]


а.

4 [ ( rational? x) " racionalni broj "]


©

5 [( real? x) " realni broj "]


иj

6 [ ( complex? x ) " k o m p l e k s n i b r o j " ]


рз

7 [ else " nije broj "] ))


ве

Слика 2.35 Дефинициjа функциjе коjа прихвата jедан аргумент, и враћа стринг чиjи
на

садржаj индикуjе скуп броjева коjем припада улазни аргумент.


д
Ра

Да jе у изразу за вишеструко гранање тока извршавања програма из-


остављен део
[ else "nije broj"] , (2.19)

10
Прецизниjа формулациjа гласи: i = argmin{î | bulovski−izraz−î = >}.
1≤î≤n
50 2 Основни инструменти апстракциjе у програмирању
 
> ( vrsta−broja 1)
" c e l i broj "
> ( v r s t a − b r o j a 1 /2 )
" racionalni broj "
> ( v r s t a − b r o j a +i n f . 0 )
" realni broj "
> ( v r s t a − b r o j a 3+5 i )
" kompleksni b r o j "
> ( vrsta−broja " broj ")
" nije broj "
 

Слика 2.36 Илустрациjа извршавања функциjе дефинисане на сл. 2.35.

функциjа не би генерисала вредност у случаjевима кад jоj се саопшти


.
ић
улазни аргумент коjи ниjе броj (в. задатак 2.3).
Треба приметити да редослед навођења логичких услова у изразу за
ов

а.
вишеструко гранање ниjе произвољан. Ако логички услови нису екслу-
ат

ан
зивно дисjунктни, потребно jе да се наведу у редоследу од наjспецифич-
Гњ

ж
ниjег ка наjопштиjем. Да бисмо то илустровали, посматраjмо дефинициjу

др
функциjе дату на сл. 2.37, у коjоj су логички услови у изразу за више-
ан

струко гранање наведени у обрнутом редоследу у односу на дефинициjуза


функциjе дату на сл. 2.35, тj., од наjопштиjег услова ка наjспецифич-
ил

ниjем. Промена редоследа навођења логичких услова доводи до следе-


су
М

ћег проблема: ако jе улазни аргумент броj, функциjа генерише стринг


а

"kompleksni broj", jер jе вредност првог логичког услова (complex? x)


1.

ав

jеднака #t, без обзира на врсту броjа (в. секциjу 1.4.1, у 1. поглављу).
02

пр

Извршавање ове функциjе илустровано jе на сл. 2.38.


–2

а
20

Св

1 ( define ( v r s t a − b r o j a x )
20

2 ( cond
а.

3 [ ( complex? x ) " k o m p l e k s n i b r o j " ]


©

4 [( real? x) " realni broj "]


иj

5 [ ( rational? x) " racionalni broj "]


рз

6 [ ( integer? x) " c e l i broj "]


7 [ else " nije broj "] ))
ве
на

Слика 2.37 Илустрациjа неадекватног редоследа навођења логичких услова у изра-


зу за вишеструко гранање тока извршавања програма.
д
Ра

Пример 2.14. Дефинишимо функциjу коjа прихвата реални броj x и вра-


ћа вредност: 
1,
 ако важи x > 0 ,
sgn(x) = 0, ако важи x = 0 , (2.20)
−1, у супротном .


2.3 Условно извршавање 51
 
> ( vrsta−broja 1)
" kompleksni b r o j "
> ( v r s t a − b r o j a 1 /2 )
" kompleksni b r o j "
> ( v r s t a − b r o j a +i n f . 0 )
" kompleksni b r o j "
> ( v r s t a − b r o j a 3+5 i )
" kompleksni b r o j "
> ( vrsta−broja " broj ")
" nije broj "
 

Слика 2.38 Илустрациjа извршавања функциjе дефинисане на сл. 2.37.

Два начина да се дефинише тражена функциjа приказана су на сл.


.
ић
2.39 и 2.40.
ов

а.
ат

ан
1 ( define ( sgn x )
2 ( i f (> x 0 )
Гњ

ж
3 1

др
4 ( i f (= x 0 ) 0 −1 ) ) )
ан

за
ил

Слика 2.39 Дефинициja функциje sgn.


су
М

а
1.

ав
02

пр

1 ( define ( sgn x )
–2

2 ( cond
3 [ (> x 0 ) 1 ]
а
20

Св

4 [ (= x 0 ) 0 ]
5 [ e l s e −1 ] ) )
20

а.
©

иj

Слика 2.40 Друга дефинициja функциje sgn.


рз
ве

Вредности израза за условно извршавање и вишеструко гранање нису


на

ограничене на домене атомских (и сложених) типова података, већ могу


д

бити и функциjе, што jе илустровано у следећем примеру.


Ра

Пример 2.15. Дефинишимо функциjу коjа прихвата реални броj x и вра-


ћа вредност: 
x + 1, ако важи x > 0 ,

f (x) = 0, ако важи x = 0 , (2.21)
x − 1, у супротном .


52 2 Основни инструменти апстракциjе у програмирању

Jедно интуитивно решење овог проблема дато jе на сл. 2.41. Мање


интуитивна дефинициjа функциjе, с изразом за условно извршавање коjи
враћа функциjу, дата jе на сл. 2.42, а приказ извршавања ове функциjе
кад jоj се саопште изабрани улазни аргументи дат jе на сл. 2.43.

1 ( define ( f x )
2 ( cond
3 [ (> x 0 ) (+ x 1 ) ]
4 [ (= x 0 ) 0 ]
5 [ e l s e (− x 1 ) ] ) )

Слика 2.41 Дефинициja функциje (2.21).

.
ић
ов

а.
1 ( define ( f x )
ат

ан
2 ( ( i f (> x 0 ) + −) x ( i f (= x 0 ) 0 1 ) ) )
Гњ

ж
др
Слика 2.42 Друга дефинициja функциje (2.21).
ан

за
ил

су
М

( f 3)
а

( ( i f (> 3 0 ) + −) 3 ( i f (= 3 0 ) 0 1 ) )
1.

ав

( ( i f #t + −) 3 ( i f #f 0 1 ) )
02

пр

(+ 3 1 )
4
–2

а
20

Св

( f 0)
( ( i f (> 0 0 ) + −) 0 ( i f (= 0 0 ) 0 1 ) )
20

( ( i f #f + −) 0 ( i f #t 0 1 ) )
а.
©

(− 0 0 )
иj

0
рз

( f −2)
ве

( ( i f (> −2 0 ) + −) −2 ( i f (= −2 0 ) 0 1 ) )
( ( i f #f + −) −2 ( i f #f 0 1 ) )
на

(− −2 1 )
−3
д
Ра

Слика 2.43 Приказ извршавања функциjе дефинисане на сл. 2.42 кад jоj се саопштe
изабрани улазни аргументи.

Иако функциjе дате на сл. 2.41 и 2.42 генеришу исте резултате кад им
се саопште исти улазни аргументи, постоjи разлика у квалитету програм-
ског ко̂да. Ко̂д приказан на сл. 2.42 jе концизниjи од ко̂да приказаног на
2.4 Функциjе вишег реда и безимене функциjе 53

сл. 2.41, али и знатно тежи за интерпретирање. Треба имати у виду да


писање ко̂да коjи jе тежак за разумевање не спада у добру праксу, посеб-
но кад постоjи могућност да се проблем реши интуитивним ко̂дом коjи
jе подjеднако или приближно ефикасан.

2.4 Функциjе вишег реда и безимене функциjе

У свим претходним примерима функциjа, вредности улазних аргуме-


ната и генерисаних резултата увек су припадале неком од домена атом-
ских типова података. За разлику од њих, под функциjама вишег реда
подразумеваjу се функциjе коjе:

.
• прихватаjу функциjе као улазне аргументе, или
ић
• враћаjу функциjе као резултат извршавања.
ов

а.
Размотримо прво пример функциjе коjа прихвата друге функциjе као
ат

ан
улазне аргументе.
Гњ

ж
Пример 2.16. Дефинишимо функциjу f коjа прихвата:

др
ан

• две функциjе g : R2 → R и h : R2 → R,
за
• и два реална броjа x и y,
ил

су

а као резултат генерише следећу вредност:


М

а
1.

ав

(
g(x, y), ако важи g(x, y) ≥ h(x, y) ,
f (g, h, x, y) = max { fˆ(x, y)} = (2.22)
02

пр

ˆf ∈{g,h} h(x, y), у супротном .


–2

Дефинициjа ове функциjе дата jе на сл. 2.44, а њено извршавање илу-


20

Св

стровано jе на сл. 2.45. У првом позиву на сл. 2.45:


20

а.

( f + − 1 2) , (2.23)
©

иj

функциjи f се, као улазни аргументи, саопштаваjу оператори + и −, и


рз

броjеви 1 и 2. Пошто jе 1 + 2 ≥ 1 − 2, функциjа f генерише вредност 3 (тj.,


ве

max{1 + 2, 1 − 2}) као резултат.


Примена функциjе f ниjе ограничена на просте операторе, већ jоj се
на

могу саопштити произвољне функциjе коjе прихватаjу два броjа и ге-


д

неришу вредност коjа се може поредити оператором >. Нпр., у трећем


Ра

позиву на сл. 2.45, функциjи f саопштена jе, као први улазни аргумент,
функциjа maks2 — претходно дефинисана на сл. 2.17, у примеру 2.8 —
коjа израчунава максимум два реална броjа.
У општем случаjу, функциjе g и h могу да буду произвољно сложе-
не, тj., њихово извршавање може да захтева процесорско време или ме-
мориjски простор коjи нису занемарљиви. Имаjући то у виду, може се
54 2 Основни инструменти апстракциjе у програмирању

1 ( define ( f g h x y )
2 ( i f (>= ( g x y ) ( h x y ) )
3 (g x y)
4 (h x y )))

Слика 2.44 Пример функциjе коjа прихвата друге функциjе као улазне аргументе.
 
> ( f + − 1 2)
3
> ( f + − −1 −2)
1
> ( f maks2 − 1 2 ) ← дефинициjа функциjе maks2 дата jе на сл. 2.17
2
 

.
ић
Слика 2.45 Илустрациjа извршавања функциjе дефинисане на сл. 2.44.
ов

а.
ат

ан
приметити да ко̂д дат на сл. 2.44 ниjе оптималан, jер се jедна од функ-
циjа g и h (прецизниjе: она функциjа коjа враћа већи резултат кад jоj се
Гњ

ж
саопште броjеви x и y) израчунава два пута — први пут кад се пореде

др
вредности ове две функциjе (линиjа 2. на сл. 2.44), а други пут кад се
ан

за
израчунава повратна вредност функциjе (линиjе 3. или 4. на сл. 2.44). У
ил

ефикасниjем приступу, вредности функциjа g и h израчунавале би се са-


су

мо jедном, и памтиле у радноj мемориjи, да би, након њиховог поређења,


М

већа вредност била прослеђена као резултат функциjе f . Овакво решење


а
1.

ав

размотрено jе у примеру 2.26.


02

пр

У наредном примеру размотрићемо функциjу коjа као резултат извр-


–2

шавања враћа функциjу.


а
20

Св

Пример 2.17. Дефинишимо функциjу f коjа прихвата:


20

а.

• две функциjе g : R2 → R и h : R2 → R,
©

иj

• и два реална броjа x и y,


рз

а резултат генерише на следећи начин:


ве

(
g, ако важи g(x, y) ≥ h(x, y) ,
на

f (g, h, x, y) = argmax{ fˆ(x, y)} = (2.24)


fˆ∈{g,h} h, у супротном ,
д
Ра

тj., функциjа f као резултат не враћа вредност, већ функциjу — и то


ону од функциjа g и h коjа генерише већу вредност кад jоj се саопште
броjеви x и y, а у случаjу да обе функциjе генеришу исту вредност, враћа
се функциjа g.
Дефинициjа функциjе дата jе на сл. 2.46. Ова функциjа пореди вред-
ности функциjа g и h за пар улазних аргумената x и y, али, за разлику
од функциjе посматране у претходном примеру, резултат израчунавања
2.4 Функциjе вишег реда и безимене функциjе 55

1 ( define ( f g h x y )
2 ( i f (>= ( g x y ) ( h x y ) ) g h ) )

Слика 2.46 Пример функциjе коjа као резултат враћа другу функциjу.

израза за условно извршавање чине функциjе g или h, а не њихове вред-


ности11 .
Извршавање функциjе илустровано jе на сл. 2.47. У првом позиву на
сл. 2.47:
( f + − 1 2) , (2.25)
функциjи f се, као улазни аргументи, саопштаваjу оператори + и −, и
броjеви 1 и 2. Пошто jе 1 + 2 ≥ 1 − 2, функциjа f враћа оператор + као
.
ић
резултат. У другом изразу на сл. 2.47, резултату извршавања подизраза
( f + − 1 2) саопштаваjу се улазни аргументи 3, 4 и 5, а израчунавање се
ов

а.
врши кроз следеће кораке:
ат

ан
(( f + − 1 2) 3 4 5) ,
Гњ

ж
(+ 3 4 5) , (2.26)

др
ан

12 . за
ил

су
М

 
а

> ( f + − 1 2)
1.

ав

#<procedure :+>
02

> ( ( f + − 1 2) 3 4 5)
пр

12
–2

> ( f + − −1 −2)
а
20

#<procedure :−>
Св

> ( ( f + − −1 −2) 3 4 5 )
20

−6
а.

> ( f maks2 − 1 2 ) ← дефинициjа функциjе maks2 дата jе на сл. 2.17


©

иj

#<procedure : maks2>
> ( ( f maks2 − 1 2 ) 3 4 )
рз

4
 
ве
на

Слика 2.47 Илустрациjа извршавања функциjе дефинисане на сл. 2.46.


д
Ра

У два претходна примера показали смо да се функциjама могу саоп-


штити, као улазни аргументи, друге функциjе коjе jе дефинисао програ-
мер. Ако jе функциjа коjа се саопштава синтаксички jедноставна и не
позива се на другим местима у програму, онда њено засебно дефиниса-
11
Због тога, у овоj функциjи ниjе присутан проблем поновног (и непотребног) изра-
чунавања вредности функциjа g и h.
56 2 Основни инструменти апстракциjе у програмирању

ње непотребно оптерећуjе структуру програма (посебно ако jе удео ова-


квих „помоћних” функциjа у програму незанемарљив). У функционал-
ном програмирању постоjи концепт безимене функциjе, коjи омогућава
дефинисање оваквих функциjа на начин коjи мање оптерећуjе структуру
програма.
У општем случаjу, синтаксичка структура дефинициjе безимене функ-
циjе jе:
(lambda (niz−ulaznih−argumenata) izraz) . (2.27)
Први елемент ове синтаксичке структуре чини симбол12 lambda, други
елемент jе низ улазних аргумената наведених у заградама (без навођења
имена функциjе), а трећи елемент чини подизраз коjи израчунава вред-
ност безимене функциjе.

.
Пример 2.18. У примеру 2.3 дефинисана jе функциjа f (x) = x2 , за x ∈ C
ић
(в. сл. 2.4). На сл. 2.48 дефинисана jе еквивалентна безимена функци-
ов

jа, њена синтаксичка структура разложена jе на сл. 2.49, а позивање jе

а.
илустровано на сл. 2.50.
ат

ан
Гњ

ж
др
1 (lambda ( x ) ( ∗ x x ) )
ан

за
ил

Слика 2.48 Безимена функциjа коjа прихвата броj x као улазни аргумент, и израчу-
су
нава вредност x2 .
М

а
1.

ав
02

пр

Слика 2.49 Синтаксичка ( lambda ( x ) (* x x) )


–2

структура дефинициjе
а

функциjе дате на сл. 2.48. безимена функциjа


20

Св

коjа прихвата аргумент x


20

и израчунава вредност x2
а.
©

иj
рз

 
ве

> (lambda ( x ) ( ∗ x x ) )
#<procedure>
на

> ( ( lambda ( x ) ( ∗ x x ) ) 2 )
4
д

> ( ( lambda ( x ) ( ∗ x x ) ) −1 . 5 )
Ра

2.25
> ( ( lambda ( x ) ( ∗ x x ) ) 1+2 i )
−3+4 i
 

Слика 2.50 Позивање безимене функциjе.

12
Tрадиционални значаj симбола lambda обjашњен jе у 4. поглављу, в. секциjу 4.7.
2.5 Локалне променљиве и лексички опсези 57

Разлика у односу на дефинициjу дату на сл. 2.4 jе у томе што ниjе


наведено име функциjе. Формално посматрано, функциjа приказана на
сл. 2.4 могла би се дефинисати на алтернативни начин, тако што бисмо
безименоj функциjи коjа израчунава квадрат броjа доделили име. У том
смислу, дефинициjа дата на сл. 2.51 еквивалентна jе дефинициjи датоj
на сл. 2.4, и делимично синтаксички сложениjа од ње.

1 ( define f 1 (lambda ( x ) ( ∗ x x ) ) )

Слика 2.51 Пример дефинисања функциjе додељивањем имена безименоj функциjи.

Пример 2.19. Безимена верзиjа функциjе maks2, коjа прихвата два реал-
.
ић
на броjа, и као резултат враћа већи од њих (в. сл. 2.17, пример 2.8), дата
ов
jе на сл. 2.52. На сл. 2.53, ова безимена функциjа саопштена jе као улазни

а.
аргумент функциjи дефинисаноj на сл. 2.46.
ат

ан
Гњ

ж
др
1 (lambda ( x y ) ( i f (>= x y ) x y ) )
ан

за
Слика 2.52 Безимена функциjа коjа прихвата два реална броjа, и као резултат враћа
ил

су
већи од њих. Функциjа f дефинисана jе на сл. 2.46.
М

а
1.

ав

 
02

пр

> ( f (lambda ( x y ) ( i f (>= x y ) x y ) ) − 1 2 )


–2

#<procedure>
а
20

> ( ( f (lambda ( x y ) ( i f (>= x y ) x y ) ) − 1 2 ) 3 4 )


Св

4
20

 
а.
©

Слика 2.53 Саопштавање безимене функциjе као улазног аргумента.


иj
рз
ве

Применa безимених функциjа биће додатно размотрена у 4. поглављу


(в. секциjу 4.5).
д на
Ра

2.5 Локалне променљиве и лексички опсези

Свака променљива има своjу област видљивости, тj., лексички опсег у


коjем се може референцирати. У секциjи 2.1 овог поглавља представили
смо глобалне променљиве. Ове променљиве називамо глобалним, jер њи-
хов лексички опсег обухвата цели програм. За разлику од њих, локалне
58 2 Основни инструменти апстракциjе у програмирању

променљиве имаjу лексичке опсеге коjи су ограничени на поjедине дело-


ве програма. Нпр., улазни аргументи представљаjу локалне променљиве
чиjи jе лексички опсег ограничен на тело функциjе.
Пример 2.20. Посматраjмо програмски ко̂д дат на сл. 2.54. Улазни ар-
гумент a jе локална променљива, видљива само у телу функциjе f , и
покушаj да се ова променљива референцира ван тела функциjе индикуjе
грешку.

 
> ( define ( f a ) (+ a 1 ) )
> ( define b (+ 3 a ) ) ← променљива a ниjе видљива ван функциjе f
. . . a : undefined ;
ca nn ot r e f e r e n c e an i d e n t i f i e r b e f o r e i t s d e f i n i t i o n
 
.
ић
Слика 2.54 Лексички опсег улазног аргумента.
ов

а.
ат

ан
Пример 2.21. Имена локалних и глобалних променљивих могу бити иден-
Гњ

ж
тична. Посматраjмо програмски ко̂д дат на сл. 2.55. У 1. линиjи дефи-

др
нисана jе глобална променљива a, чиjи лексички опсег обухвата цели
ан

програм. У 3. линиjи дефинисана jе функциjа f , с улазним аргументом a


за
ил

коjи представља локалну променљиву чиjи jе лексички опсег ограничен


су

само на тело функциjе f .


М

У оквиру свог лексичког опсега, локална променљива a сакрива гло-


а
1.

балну променљиву a, тако да се навођењем имена a у телу функциjе f


ав

референцира локална променљива a. С друге стране, навођењем имена


02

пр

a ван тела функциjе референцира се глобална променљива a. Нпр., у 5.


–2

линиjи ко̂да датог на сл. 2.55, збир вредности глобалне променљивe a и


а
20

Св

броjа 3 саопштава се као улазни аргумент функциjи f . Референцирања


20

променљивих назначена су усмереним линиjама.


а.
©

иj

1 ( define a 1 ) ← глобална променљива a


рз

2
( define ( f a ) (+ a 1 ) )
ве

3 ← локална променљива a
4
5 ( f (+ 3 a ) ) ← референцирање глобалнe променљивe a
д на
Ра

Слика 2.55 Идентична имена глобалних и локалних променљивих.

Пример 2.22. Имена улазних аргумената различитих функциjа такође


могу бити идентична. Посматраjмо програмски ко̂д дат на сл. 2.56. У
1. линиjи дефинисана jе функциjа f са улазним аргументом a коjи пред-
ставља локалну променљиву чиjи jе лексички опсег ограничен само на
2.5 Локалне променљиве и лексички опсези 59

тело функциjе f . У 3. линиjи дефинисана jе функциjа g са улазним ар-


гументом a коjи представља локалну променљиву чиjи jе лексички оп-
сег ограничен само на тело функциjе g. Референцирања променљивих
назначена су усмереним линиjама. Пошто се, у овом примеру, лексички
опсези истоимених променљивих не преклапаjу, не постоjи могућност ви-
шесмисленог интерпретирања имена променљиве — а, у складу с тим, ни
могућности међусобног скривања.

1 ( define ( f a ) (+ a 1 ) ) ← локална променљива a


2
3 ( define ( g a ) (+ a 1 ) ) ← локална променљива a

.
Слика 2.56 Идентична имена улазних аргумената различитих функциjа.
ић
ов

а.
ат

ан
Пример 2.23. Посматраjмо програмски ко̂д дат на сл. 2.57, у ком су име-
на x и y придружена двема глобалним и трима локалним променљивама,
Гњ

ж
при чему су референцирања променљивих назначена усмереним лини-

др
jама. Навођењем имена y у телу функциjе f референцира се глобална
ан

за
променљива y, jер у функциjи f ниjе дефинисана локална променљива y
ил

коjа би сакрила истоимену глобалну променљиву. За разлику од тога, на-


су

вођењем имена y у телу функциjе g референцира се локална променљива


М

y коjа сакрива истоимену глобалну променљиву. Приказ израчунавања


а
1.

ав

овог програма дат jе на сл. 2.58.


02

пр
–2

1 ( define x 1 ) ← глобална променљива x


а
20

2
Св

3 ( define y 3) ← глобална променљива y


20

4
а.

y ))
©

5 ( define ( f x ) (− x ← локална пром. x и глобална пром. y


иj

6
7 ( define ( g x y ) (− x y )) ← локалнe променљивe x и y
рз

8
ве

9 ( f (g y x ))) ← референцирање глобалних променљивих x и y


на

Слика 2.57 Истоимене променљиве и лексички опсези.


д
Ра

Успостављање лексичких опсега променљивих спада у фундаментал-


не аспекте програмских jезика. Програмер коjи имплементира одређену
функциjу не мора, а често ни не може, да има увид у све променљиве
окружења. Могућност дефинисања различитих променљивих са иден-
тичним именима и функционалност сакривања „спољашње” променљиве
60 2 Основни инструменти апстракциjе у програмирању

(f (g y x))
(f (g 3 1))
(f (− 3 1 ) )
(f 2)
(− 2 3)
−1

Слика 2.58 Приказ израчунавања програма датог на сл. 2.57.

истоименом локалном променљивом ослобађаjу програмера обавезе да


води рачуна о променљивама окружења, и допуштаjу му да флексибил-
но изабира имена променљивих, што jе суштинска погодност кад jе у
развоj програма укључено више програмера.
.
ић
ов

а.
2.5.1 Локално повезивање
ат

ан
Гњ

ж
У досадашњем разматрању, као примери локалних променљивих на-

др
вођени су искључиво улазни аргументи, а њихови лексички опсези одго-
ан

за
варали су увек телу функциjе. Међутим, програмер може и прецизниjе
ил

да дефинише лексичке опсеге своjих локалних променљивих. У наставку


су

ћемо размотрити два начина за дефинисање лексичких опсега:


М

• паралелно локално повезивање,


1.

ав

• секвенциjално локално повезивање.


02

пр

Синтаксичка структура израза за паралелно локално повезивање при-


–2

казана jе на сл. 2.59. Овим изразом дефинише се скуп локалних промен-


а
20

Св
20

 
а.

( let
©

( [ promenljiva−1 izraz−1 ]
иj

[ promenljiva−2 izraz−2 ]
рз

...
[ promenljiva − n i z r a z − n ] )
ве

izraz )
 
д на

Слика 2.59 Синтаксичка структура израза за паралелно локално повезивање.


Ра

љивих:
promenljiva−1, promenljiva−2, ..., promenljiva−n , (2.28)
коjе се респективно повезуjу с вредностима израза:

izraz−1, izraz−2, ..., izraz−n , (2.29)


2.5 Локалне променљиве и лексички опсези 61

и имаjу заjеднички лексички опсег, тj., дефинисане локалне променљиве


могу се референцирати само у изразу izraz — чиjа вредност представља
коначну вредност израза представљеног на сл. 2.59. Дефинисање локал-
них променљивих одвиjа се „паралелно” 13 , тj., ниjе дозвољено да се у
изразу за дефинисање вредности неке локалне променљиве референцира
име друге локалне променљиве из истог лексичког опсега.

Пример 2.24. Примери паралелног локалног повезивања дати су на сл.


2.60. Референцирања локалних променљивих назначена су усмереним ли-
ниjама.

 
> ( l e t ( [ x 1 ] ) (+ x 2 ) )
3
> ( l e t ( [ x 1 ] [ y 2 ] ) (+ x
.
y ))
ић
3
 
ов

а.
ат

ан
Слика 2.60 Примери паралелног локалног повезивања.
Гњ

ж
др
ан

Пример 2.25. Дефинишимо функциjу:


за
ил

су
f (a, b, c) = max{a, b, c} − min{a, b, c} , (2.30)
М

за a, b, c ∈ R.
1.

ав

За решавање овог проблема применићемо две помоћне функциjе коjе


02

пр

респективно израчунаваjу максималну вредност и минималну вредност


–2

низа броjева a, b, c. У примеру 2.9 дефинисана jе функциjа maks3 коjа


а

прихвата три реална броjа, и као резултат враћа наjвећи од њих. Аналог-
20

Св

но, могли бисмо дефинисати функциjу коjа прихвата три реална броjа,
20

и као резултат враћа наjмањи од њих. Међутим, овде ћемо применити


а.
©

две општиjе функциjе коjе су унапред дефинисане у програмском jезику


иj

Ракет:
рз

• max — прихвата произвољни14 броj реалних вредности, и враћа наjве-


ве

ћу од њих,
• min — прихвата произвољни броj реалних вредности, и враћа наjмању
на

од њих.
д
Ра

13
У овом контексту, прилошку одредбу „паралелно” треба схватити условно. Она само
означава да ниjе дозвољено да се у изразу за дефинисање вредности неке локалне
променљиве референцира име друге локалне променљиве из истог лексичког опсега.
Међутим, дефинисање локалних променљивих извршава се у редоследу навођења.
14
У 4. поглављу (в. секциjу 4.6) ћемо показати како се дефинишу функциjе коjе
прихватаjу произвољни броj улазних аргумената.
62 2 Основни инструменти апстракциjе у програмирању

Дефинициjа функциjе са локалним променљивама коjа израчунава


вредност функциjе (2.30) дата jе на сл. 2.61. Ова функциjа би се мо-
гла представити и синтаксички jедноставниjом дефинициjом, без увође-
ња локалних променљивих (в. сл. 2.62). Међутим, понекад се увођењем
локалних променљивих постиже ефикасниjе решење, што jе илустрoвано
у наредном примеру.

1 ( define ( f a b c )
2 ( let
3 ( [ maksimum (max a b c ) ]
4 [ minimum ( min a b c ) ] )
5 (− maksimum minimum ) ) )

.
Слика 2.61 Дефинициjа функциjе (2.30), са локалним променљивама.
ић
ов

а.
ат

ан
1 ( define ( f a b c )
Гњ

ж
2 (− (max a b c ) ( min a b c ) ) )

др
ан

за
Слика 2.62 Дефинициjа функциjе (2.30), без увођења локалних променљивих.
ил

су
М

Пример 2.26. У примеру 2.16 истакнуто jе да дефинициjа функциjе дата


а

на сл. 2.44 ниjе оптимална, jер се jедна од функциjа g и h израчунава два


1.

ав

пута — први пут кад се пореде вредности ове две функциjе (линиjа 2.
02

пр

на сл. 2.44), а други пут кад се израчунава повратна вредност функциjе


–2

(линиjе 3. или 4. на сл. 2.44, у зависности од вредности функциjа).


а
20

У овом примеру приказано jе ефикасниjе решење, у коjем се вредности


Св

функциjа g и h израчунаваjу само jедном, и памте у локалним промен-


20

љивама, да би, након њиховог поређења, већа вредност била прослеђена


а.
©

као резултат функциjе. Дефинициjа функциjе дата jе на сл. 2.63.


иj
рз
ве

1 ( define ( f g h x y )
2 ( let
на

3 ( [ gv ( g x y ) ]
4 [ hv ( h x y ) ] )
д

5 ( i f (>= gv hv ) gv hv ) ) )
Ра

Слика 2.63 Ефикасниjа дефинициjа функциjе претходно приказане на сл. 2.44.

Синтаксичка структура израза за секвенциjално локално повезивање


приказана jе на сл. 2.64. Разлике овог израза у односу на израз за пара-
лелно локално повезивање (в. сл. 2.59) су следеће:
2.5 Локалне променљиве и лексички опсези 63

• У изразу за секвенциjално повезивање, непосредно после симбола let


налази се симбол ∗.
• Дефинисање локалних променљивих одвиjа се „секвенциjално”, тj., до-
звољено jе да се у изразу за дефинисање вредности неке локалне про-
менљиве референцира име друге локалне променљиве из истог лек-
сичког опсега коjа jе претходно дефинисана.

 
( let ∗
( [ promenljiva−1 izraz−1 ]
[ promenljiva−2 izraz−2 ]
...
[ promenljiva − n i z r a z − n ] )
izraz )
 
.
ић
ов
Слика 2.64 Синтаксичка структура израза за секвенциjално локално повезивање.

а.
ат

ан
Гњ

ж
Пример 2.27. Дефинишимо сигмоидну функциjу:

др
ан

ex за
s(x) = , (2.31)
ex + 1
ил

су

где e представља Оjлеров броj (e ≈ 2, 718281828459045).


М

Jедна од могућих дефинициjа функциjе дата jе на сл. 2.65. У овом


а
1.

ав

партикуларном решењу, применом израза за секвенциjално локално по-


02

везивање постигнуто jе да се вредност ex израчунава15 само jедном. Ова


пр

вредност додељуjе се локалноj променљивоj коjа представља броjилац


–2

разломка (2.31). Приликом израчунавања имениоца разломка (2.31), уме-


а
20

Св

сто поновног израчунавања вредности ex , референцира се претходно де-


20

финисана локална променљива.


а.
©

иj

1 ( define ( f x )
рз

2 ( let ∗
ве

3 ( [ b r o j i l a c ( exp x ) ]
4 [ i m e n i l a c (+ b r o j i l a c 1 ) ] )
на

5 (/ b r o j il a c imenilac )))
д
Ра

Слика 2.65 Дефинициjа сигмоидне функциjе.

15
У овом решењу користимо унапред дефинисану функциjу exp коjа прихвата броj x и
израчунава вредност ex — и коjу треба разликовати од унапред дефинисане функциjе
expt представљене у 1. поглављу, в. пример 1.14.
64 2 Основни инструменти апстракциjе у програмирању

Из описа функционалности израза за локално повезивање, било би


погрешно стећи утисак да се израз за секвенциjално локално повезивање
може увек примењивати уместо израза за паралелно локално повезивање.
У случаjевима кад jе могуће применити било коjи од ова два израза,
избором израза за паралелно локално повезивање добиjа се читљивиjи
ко̂д, jер се наглашава да не постоjе везе између локалних променљивих
коjе деле лексички опсег. С друге стране, понекад избор ниjе произвољан,
што jе илустовано у следећем примеру.

Пример 2.28. Изрази за локално повезивање могу се међусобно угнежђи-


вати. Упоредимо изразе дате на сл. 2.66. Jедина разлика између њих jе
та што jе у изразу (а) угнежђен израз за паралелно локално повезивање,
док jе у изразу (б) угнежђен израз за секвенциjално локално повезива-
ње. У првом случаjу, променљива x дефинисана у 4. линиjи израза ниjе
.
ић
видљива приликом дефинисања променљиве y, па се навођењем имена x
у 5. линиjи израза референцира променљива x из надређеног лексичког
ов

а.
опсега, дефинисана у 2. линиjи. У другом случаjу, променљива x дефини-
ат

ан
сана у угнежђеном лексичком опсегу видљива jе приликом дефинисања
Гњ

променљиве y, и сакрива променљиву x из надређеног лексичког опсега.

ж
Последично, вредности израза (а) и (б) се разликуjу — вредности првог

др
израза jеднака jе 2, а другог 3. Референцирања променљивих назначена
ан

су усмереним линиjама.
за
ил

су

 
М

1 > ( let
а
1.

ав

2 ([ x 1])
3 ( let
02

пр

4 ([ x 2]
–2

5 [ y (+ x 1)]) ← y = 1+1
а

6 y))
20

Св

7 2
 
20

(а)
а.
©

иj

 
рз

1 > ( let
2 ([ x 1])
ве

3 ( let ∗
4 ([ x 2]
на

5 [ y (+ x 1)]) ← y = 2+1
6 y))
д

7 3
Ра

 
(б)

Слика 2.66 Угнежђивање израза за локално повезивање.


2.6 Подразумеване вредности улазних аргумената 65

2.6 Подразумеване вредности улазних аргумената

Приликом представљања функциjа16 у секциjи 1.5 (в. 1. поглавље),


видели смо да улазни аргументи могу да имаjу подразумеване вредно-
сти. Ако се вредност оваквог аргумента експлицитно наведе приликом
позивања функциjе, функциjа узима у обзир саопштену вредност. У су-
протном, функциjа узима у обзир подразумевану вредност аргумента.
Две типичне ситуациjе у коjима се дефинишу улазни аргументи с под-
разумеваним вредностима су:
• кад проценимо да ће се функциjи учестало саопштавати jедна кон-
кретна вредност датог улазног аргумента, а само спорадично друге
вредности (в. пример 2.29),
• постављање почетне вредности променљиве у коjоj ће се „акумули-
.
ић
рати” резултати израчунавања секвенце репно-рекурзивних позива
функциjе (што jе обjашњено у 3. поглављу).
ов

а.
Синтаксичка структура дела израза коjи дефинише улазни аргумент
ат

ан
с подразумеваном вредношћу jе:
Гњ

ж
др
[ ulazni−argument podrazumevana−vrednost] , (2.32)
ан

за
и илустрована jе у следећем примеру.
ил

су

Пример 2.29. У примеру 1.9 (1. поглавље) показали смо да резултати


М

непрецизног одузимања броjева могу да одступаjу од очекиваних вред-


а
1.

ав

ности, тако да не можемо да их поредимо оператором = (в. сл. 2.67).


02

пр
–2

 
а
20

Св

> (− 1 0 . 9 )
0.09999999999999998
20

> (− 2 1 . 9 )
а.
©

0.10000000000000009
иj

> (= (− 1 0 . 9 ) (− 2 1 . 9 ) )
рз

#f
 
ве

Слика 2.67 Пример поређења резултата непрецизног одузимања броjева.


д на
Ра

Да бисмо превазишли оваj проблем, дефинисаћемо функциjу коjа


утврђуjе да ли су две реалне вредности „довољно блиске”, тj., усвоjићемо
правило да се вредности x и y могу сматрати jеднаким ако jе апсолутна
вредност њихове разлике мања од задате вредности прага e ∈ R, тj.:

|x − y| < e . (2.33)
16
Мисли се на функциjе: substring, number−>string и string −>number.
66 2 Основни инструменти апстракциjе у програмирању

Дефинициjа функциjе коjа имплементира ово правило дата jе на сл. 2.68.


Ова функциjа прихвата три улазна аргумента: x, y и e, при чему jе по-
следњем аргументу додељена подразумевана вредност. Тиме jе корисни-
ку функциjе остављена могућност да експлицитно спецификуjе вредност
прага коjу сматра одговараjућом за поређење вредности x и y, али му се
не намеће обавеза да то учини, ако сматра да jе подразумевана вредност
прага одговараjућа (в. сл. 2.69).

1 ( define ( j e d n a k i ? x y [ e 0 . 0 0 0 0 0 1 ] )
2 (< ( abs (− x y ) ) e ) )

Слика 2.68 Функциjа коjа пореди непрецизне броjеве.

.
ић
ов

а.
 
ат

ан
> ( j e d n a k i ? (− 1 0 . 9 ) (− 2 1 . 9 ) )
#t
Гњ

ж
> ( j e d n a k i ? (− 1 0 . 9 ) (− 2 1 . 9 ) ( e x p t 10 −20 ) )

др
#f
 
ан

за
ил

Слика 2.69 Илустрациjа позивања функциjе дефинисане на сл. 2.68.


су
М

а
1.

ав
02

пр

2.6.1 Именовани улазни аргументи


–2

а
20

Св

Улазним аргументима могу се доделити посебна имена преко коjих се


20

врши њихово саопштавање функциjи. Такви аргументи називаjу се име-


а.
©

нованим улазним аргументима, и саопштаваjу се функциjи навођењем


иj

додељеног имена аргумента непосредно испред његове вредности, а не


рз

на основу позициjе у секвенци улазних вредности.


ве

Именовањем улазних аргумената с подразумеваним вредностима по-


стиже се да се функциjи може експлицитно саопштити произвољна ком-
на

бинациjа ових аргумената.


д

Пример 2.30. Пример функциjе коjа прихвата два именована улазна ар-
Ра

гумента с подразумеваним вредностима дат jе на сл. 2.70, а саопштавање


улазних аргумената овоj функциjи илустровано jе на сл. 2.71.
2.7 Закључне напомене 67

1 ( define ( t e s t #: p r v i [ s 1 " a " ] #: d r u g i [ s 2 "b " ] )


2 ( s t r i n g − a p p e n d " P r v i argument : " s 1
3 " , d r u g i argument : " s 2 " . " ) )

Слика 2.70 Пример функциjе коjа прихвата два именована улазна аргумента с под-
разумеваним вредностима.
 
> ( test )
" P r v i argument : a , d r u g i argument : b . "
> ( t e s t #: p r v i " c " )
" P r v i argument : c , d r u g i argument : b . "
> ( t e s t #: d r u g i "d " )
" P r v i argument : a , d r u g i argument : d . "
> ( t e s t #: p r v i " e " #: d r u g i " f " )
" P r v i argument : e , d r u g i argument : f . "
.
ић
> ( t e s t #: d r u g i " e " #: p r v i " f " )
" P r v i argument : f , d r u g i argument : e . "
ов

 

а.
ат

ан
Слика 2.71 Илустрациjа саопштавања улазних аргумената функциjи дефинисаноj
Гњ

ж
на сл. 2.70.

др
ан

2.7 Закључне напомене


за
ил

су
М

Поглавље ћемо завршити кратким увидом у jедан партикуларни аспект


а

организациjе рачунара. Позивни стек jе линеарна динамичка структу-


1.

ав

ра у радноj мемориjи коjа има важну улогу у програмском извршавању


02

пр

функциjа. Сваки пут кад се позове нека функциjа, у позивни стек се


–2

привремено ставља тзв. оквир стека, коjи садржи податке релевантне за


а

контекст у коjем jе функциjа позвана, укључуjући:


20

Св
20

• корисничке податке (тj., вредности саопштених улазних аргумената и


а.

других локалних променљивих),


©

иj

• податке за контролу извршавања програма, коjи, између осталог, омо-


гућаваjу наставак извршавања програма након повратка из функциjе.
рз
ве

Непосредно након извршења функциjе, оквир стека коjи jу jе предста-


вљао уклања се из позивног стека.
на

Пример 2.31. Посматраjмо програм приказан на сл. 2.72. У телу функ-


д
Ра

циjе f позива се функциjа g, а у телу функциjе g позива се функциjа h.


Поступак израчунавања функциjе f кад jоj се саопшти аргумент 2 при-
казан jе на сл. 2.73, а одговараjућа секвенца стања позивног стека дата
jе на сл. 2.74.

У општем случаjу, низ угнежђених позива функциjа захтева привре-


мено чување низа оквира у позивном стеку. Манипулисање оквирима у
68 2 Основни инструменти апстракциjе у програмирању

1 ( define ( f x ) (+ 1 ( g x ) ) )
2 ( define ( g x ) ( ∗ 3 ( h x ) ) )
3 ( define ( h x ) ( ∗ x x ) )
4 ( f 2)

Слика 2.72 Програм коjи илуструjе функционалност позивног стека.


 
(f 2) ← (а) позивање функциjе f
(+ 1 (g 2)) ← (б) позивање функциjе g
(+ 1 (∗ 3 (h 2 ) ) ) ← (в) позивање функциjе h
(+ 1 (∗ 3 (∗ 2 2 ) ) )
(+ 1 (∗ 3 4)) ← (г) повратак из функциjе h
(+ 1 12) ← (д) повратак из функциjе g
13 ← (ђ) повратак из функциjе f
 
.
ић
Слика 2.73 Поступак извршавања програма датог на сл. 2.72.
ов

а.
ат

ан
ниже адресе ниже адресе ниже адресе
⇑ ⇑ ⇑
Гњ

ж
др
... ... (h 2)
ан

... (g 2) (g 2)
за
ил

( f 2) ( f 2) ( f 2)
су
М

⇓ ⇓ ⇓
1.

ав

више адресе више адресе више адресе


02

пр

(а) (б) (в)


–2

ниже адресе ниже адресе ниже адресе


а
20

Св

⇑ ⇑ ⇑
20

а.

... ... ...


©

иj

(g 2) ... ...
( f 2) ( f 2) ...
рз
ве

⇓ ⇓ ⇓
више адресе више адресе више адресе
на

(г) (д) (ђ)


д
Ра

Слика 2.74 Илустрациjа стања позивног стека за време извршавања програма датог
на сл. 2.72. Елементи у позивном стеку представљаjу оквире стека коjи одговараjу
позивима функциjа.
2.8 Задаци 69

позивном стеку може да захтева процесорско време или мемориjски про-


стор коjи нису занемарљиви — што ће бити детаљниjе размотрено у 3.
поглављу.

Библиографскe напоменe:
• Поjмови променљивих и функциjа описани су у секциjи „1.1 The
Elements of Programming”, а поjмови функциjа вишег реда и без-
имених функциjа у секциjи „1.3 Formulating Abstractions with
Higher-Order Procedures” библиографског навода [1].
• Редослед израчунавања вредности у изразима за паралелно и се-
квенциjално локално повезивање размотрен jе у секциjама „5.5
The let special function” и „5.6 The let* special function” библио-
графског навода [31].
.
ић
• Додатни облици израза за локално повезивање описани су у секе-
ов
циjи „4.6 Local Binding” библиографског навода [6].

а.
• Декларисање улазних аргумената с подразумеваним вредности-
ат

ан
ма и именованих улазних аргумената описано jе у секциjама
Гњ

ж
„4.4.2 Declaring Optional Arguments” и „4.4.3 Declaring Keyword

др
Arguments” библиографског навода [6].
ан

• Улога позивног стека у механизму за имплементирање функциjа


за
и важност провере валидности улазних аргумената описани су у
ил

поглављу „2. Прекорачење стека” библиографског навода [9].


су
М

а
1.

ав
02

пр
–2

2.8 Задаци
а
20

Св
20

Задатак 2.1. Зашто jе дефинициjа функциjе коjа израчунава запремину


а.

коцке, дата на сл. 2.29, адекватниjа од дефинициjе функциjе дате на


©

иj

сл. 2.75? (Савет: посматраjте логички услов и претпоставку редоследа


израчунавања делова израза на истом хиjерархиjском нивоу.)
рз
ве

1 ( define ( zapremina a )
на

2 ( i f ( and ( r e a l ? a ) (> a 0 ) )
д

3 ( expt a 3)
Ра

4 0))

Слика 2.75 Дефинициja функциje уз задатак 2.1.

Задатак 2.2. Дефинишите функциjу коjа прихвата три реална броjа, и


израчунава реципрочну вредност збира два наjвећа броjа.
70 2 Основни инструменти апстракциjе у програмирању

Задатак 2.3. Зашто функциjа дефинисана на сл. 2.76 не представља


адекватно решење проблема изложеног у примеру 2.13? (Савет: посма-
траjте шта се дешава кад функциjи саопштите вредност коjа ниjе броj.)

( define ( v r s t a − b r o j a x )
( cond
[ ( integer? x) " c e l i broj "]
[ ( rational? x) " racionalni broj "]
[( real? x) " realni broj "]
[ else " kompleksni b r o j " ] ) )

Слика 2.76 Дефинициja функциje уз задатак 2.3.

.
ић
Задатак 2.4. Коjа jе вредност израза датог на сл. 2.77? Обjасните.
ов

а.
ат

ан
( let ( [ x 1])
Гњ

ж
( let ( [ x 2]

др
[y x])
ан

(+ x y ) ) ) за
ил

су

Слика 2.77 Израз уз задатак 2.4.


М

а
1.

ав
02

пр
–2

а
20

Св
20

а.
©

иj
рз
ве
д на
Ра
Поглавље 3
Рекурзивне функциjе

.
ић
3.1 Увод
ов

а.
ат

ан
Рекурзиjа спада у централне концепте програмирања. У овом погла-
вљу размотрићемо jедан партикуларни аспект овог концепта — рекурзив-
Гњ

ж
не функциjе. Под рекурзивним функциjама подразумеваjу се функциjе

др
коjе у току свог извршавања позиваjу саме себе, што ћемо у наставку
ан

за
називати рекурзивним позивом. Jедна од наjочигледниjих особина ре-
ил

курзивних функциjа jе та да омогућаваjу примену коначних израза за


су

генерисање неограниченог1 броjа обjеката, што омогућава дизаjн конци-


М

зних и интуитивних решења.


а
1.

ав

Поступак дизаjнирања рекурзивних функциjа размотрићемо кроз низ


02

примера, с намером да истакнемо важну дистинкциjу између поjма ре-


пр

курзивне функциjе и поjма процеса коjи рекурзивна функциjа импле-


–2

ментира. Термин рекурзивна функциjа jе синтаксичка одредница коjа


а
20

Св

наглашава чињеницу да функциjа позива саму себе. Независно од син-


20

таксичког записа, рекурзивна функциjа може да имплементира две врсте


а.

процеса:
©

иj

• рекурзивни процес и
рз

• итеративни процес, коjи ћемо у овом поглављу називати репном ре-


ве

курзиjом.
Ове две врсте процеса суштински се разликуjу у односу на динамику
на

мемориjског заузећа, што ће бити детаљниjе размотрено у наставку.


д
Ра

1
Кад се каже да jе броj обjеката генерисаних рекурзивном функциjом неограничен,
мисли се на чињеницу да дизаjн рекурзивне функциjе не уводи ограничења у погледу
броjа генерисаних обjеката (иако уобичаjено садржи критериjум за престанак гене-
рисања обjеката). С друге стране, броj генерисаних обjеката ограничен jе факторима
окружења у коjима се функциjа извршава, попут капацитета радне мемориjе.

71
72 3 Рекурзивне функциjе

3.2 Рекурзивно издваjање цифара из целих броjева

Прва група примера односи се на рекурзивно издваjање цифара из


целих броjева.

3.2.1 Збир цифара ненегативног броjа

Пример 3.1. Дефинишимо рекурзивну функциjу коjа израчунава збир


цифара датог ненегативнoг целог броjа n.
Да бисмо илустровали поступак решавања овог проблема, кренимо од
поjедностављеног контекста, и посматраjмо jедну партикуларну вредност
.
улазног аргумента. Нека jе n = 1234. Очекивана вредност функциjе кад
ић
jоj се саопшти оваj улазни аргумент jе:
ов

а.
(3.1)
ат

f (1234) = 1 + 2 + 3 + 4 = 10 .

ан
Гњ

ж
Поступак израчунавања може се представити и на следећи начин:

др
ан

f (1234) = 1 + 2 + 3 + 4 за
= (1 + 2 + 3) + 4 (3.2)
ил

су

= f (123) + 4 .
М

Другим речима, збир цифара броjа n = 1234 jеднак jе збиру следећа два
1.

ав

сабирка:
02

пр

• f (123) — збирa цифара броjа коjи се добиjе кад се из n уклони последња


–2

цифра,
а
20

Св

• 4 — последњe цифрe броjа n,


20

тj.:
а.
©

f ( 123 4 ) = f ( 123 ) + 4 . (3.3)


иj

У општем случаjу, ово правило гласи:


рз
ве

n
f (n) = f (b c) + (n%10), за n ≥ 10 , (3.4)
10
на

где су:
д

n
Ра

• b c — броj коjи се добиjе кад се из n уклони последња цифра,


10
• n%10 — последња цифра броjа n.
Лако се показуjе да правило (3.4) важи за све позитивне целе броjе-
ве коjи садрже више од jедне цифре, што омогућава његову рекурзивну
примену. Рекурзивност овог правила рефлектуjе се у томе што се из-
рачунавање вредности функциjе f за улазну вредност 1234 заснива на
3.2 Рекурзивно издваjање цифара из целих броjева 73

израчунавању вредности исте функциjе f за улазну вредност 123, а изра-


чунавање вредности f (123) заснивa се на израчунавању вредности f (12),
итд.:

f (1234) = f (123) + 4
= ( f (12) + 3) + 4 (3.5)
= (( f (1) + 2) + 3) + 4 .

Међутим, рекурзивна примена правила (3.4) не може се вршити прои-


звољно дуго. Сваком применом овог правила издваjа се по jедна цифра
из броjа n, што значи да се правило може примењивати све док улазни
аргумент не постане jедноцифрени броj. Нпр., у последњем реду jедна-
кости (3.5), вредност функциjе f потребно jе израчунати за вредност 1.
.
У случаjу кад jе улазни аргумент jедноцифрени броj, збир његових
ић
цифара jеднак jе самом улазном аргументу, што се може представити
ов

следећим правилом:

а.
f (n) = n, за 0 ≤ n < 10 . (3.6)
ат

ан
Гњ

Ово правило, у ствари, представља услов за излазак из секвенце рекур-

ж
зивних позива, и његовом применом завршава се израчунавање jеднако-

др
сти (3.5):
ан

за
ил

f (1234) = f (123) + 4
су
М

= ... (3.7)
а

= (( f (1) + 2) + 3) + 4 = (( 1 + 2) + 3) + 4 = 10 .
1.

ав
02

пр

Поступак израчунавања функциjе f може се представити спаjањем


–2

рекурзивног правила (3.4) и услова за излазак из рекурзиjе (3.6):


а
20

Св

( n
f (b c) + (n%10), n ≥ 10 ,
20

f (n) = 10 (3.8)
а.

n, n < 10 .
©

иj

Рекурзивна функциjа на програмском jезику Ракет коjа имплементи-


рз

ра формулу (3.8) приказана jе на сл. 3.1. Резултат позивања ове функ-


ве

циjе кад jоj се саопшти улазни аргумент n = 1234 приказан jе на сл. 3.2.
Функциjа генерише очекивани резултат, али се из овог приказа не види
на

секвенца рекурзивних позива коjа jе извршена у поступку израчунава-


д

ња резултата. Да бисмо остварили бољи увид у поступак израчунавања


Ра

приказаног резултата, посматраћемо:


• секвенцу рекурзивних позива приликом извршавања ове функциjе кад
jоj се саопшти улазни аргумент n = 1234, приказану на сл. 3.3,
• секвенцу стања позивног стека за време извршавања ове функциjе,
илустровану на сл. 3.4.
74 3 Рекурзивне функциjе

1 ( define ( z b i r n )
2 ( i f (< n 1 0 )
3 n
4 (+ ( z b i r ( q u o t i e n t n 1 0 ) ) ( r e m a i n d e r n 1 0 ) ) ) )

Слика 3.1 Рекурзивна функциjа коjа за дати ненегативни цели броj израчунава збир
његових цифара.
 
> ( z b i r 1234)
10
 

Слика 3.2 Резултат позивања функциjе дефинисане на сл. 3.1 кад jоj се саопшти
улазни аргумент n = 1234.

.
ић
( z b i r 1234) ← (а) 1. позив функциjе
ов
(+ ( z b i r 1 2 3 ) 4 ) ← (б) 2. позив функциjе

а.
(+ (+ ( z b i r 1 2 ) 3 ) 4 ) ← (в) 3. позив функциjе
ат

ан
(+ (+ (+ ( z b i r 1 ) 2 ) 3 ) 4 ) ← (г) 4. позив функциjе
(+ (+ (+ 1 2 ) 3 ) 4 ) ← (д) повратак из 4. позива функциjе
Гњ

ж
(+ (+ 3 3 ) 4 ) ← (ђ) повратак из 3. позива функциjе

др
(+ 6 4 ) ← (е) повратак из 2. позива функциjе
ан

10 ← (ж) повратак из 1. позива


за функциjе
ил

су

Слика 3.3 Приказ рекурзивног извршавања функциjе дефинисане на сл. 3.1 кад jоj
М

се саопшти улазни аргумент n = 1234.


а
1.

ав
02

пр

Треба приметити да jе у 4. линиjи функциjе дефинисане на сл. 3.1


–2

задата операциjа сабирања у коjоj први сабирак представља повратну


а

вредност рекурзивно позване функциjе:


20

Св
20

(+ (zbir (quotient n 10)) (remainder n 10)) . (3.9)


а.
©

иj

То значи да се позивањем функциjе (zbir 1234) генерише следећи низ


рз

рекурзивних позива:
ве

• Стање позивног стека коjе одговара првом позиву функциjе (zbir 1234)
илустровано jе на сл. 3.4(а). У овом позиву, вредност збира (3.9) не мо-
на

же се израчунати док се претходно не израчуна вредност (zbir 123).


д

• Због тога, врши се други позив функциjе (zbir 123), док jош први
Ра

позив ниjе завршен, што се рефлектуjе у додавању новог оквира у


позивни стек (в. сл. 3.4(б)).
• Из истог разлога, израчунавање вредности (zbir 123) захтева прет-
ходно израчунавање вредности (zbir 12), па се трећи позив функциjе
(zbir 12) врши док претходна два позива jош нису завршена, а у по-
зивни стек се додаjе нови оквир коjи одговара трећем позиву функциjе
(в. сл. 3.4(в)).
3.2 Рекурзивно издваjање цифара из целих броjева 75

ниже адресе ниже адресе ниже адресе ниже адресе


⇑ ⇑ ⇑ ⇑

... ... ... ( zbir 1)


... ... ( zbir 12) ( zbir 12)
... ( zbir 123) ( zbir 123) ( zbir 123)
( zbir 1234) ( zbir 1234) ( zbir 1234) ( zbir 1234)

⇓ ⇓ ⇓ ⇓
више адресе више адресе више адресе више адресе
(а) (б) (в) (г)

ниже адресе ниже адресе


. ниже адресе ниже адресе
ић
⇑ ⇑ ⇑ ⇑
ов

а.
ат

... ... ... ...

ан
... ... ...
Гњ

( zbir 12)

ж
( zbir 123) ( zbir 123) ... ...

др
ан

( zbir 1234) ( zbir 1234) ( zbir 1234) за ...


ил

су

⇓ ⇓ ⇓ ⇓
М

више адресе више адресе више адресе више адресе


а
1.

ав

(д) (ђ) (е) (ж)


02

пр

Слика 3.4 Илустрациjа стања позивног стека за време рекурзивног извршавања


–2

функциjе дефинисане на сл. 3.1 кад jоj се саопшти улазни аргумент n = 1234.
а
20

Св
20

• Коначно, израчунавање вредности (zbir 12) захтева четвртo позиви-


а.
©

вање функциjе (zbir 1), док jош ниjедан од претходних позива ниjе
иj

завршен, а у позивни стек се додаjе jош jедан оквир коjи одговара


рз

четвртом позиву функциjе (в. сл. 3.4(г)).


ве

Четврти позив функциjе (zbir 1) представља последњи позив у се-


квенци рекурзивних позива, jер jе улазни аргумент jедноцифрени броj.
на

По дефинициjи функциjе приказаноj на сл. 3.1, повратна вредност овог


д

позива израчунава се директно, и jеднака jе 1. Повратне вредности ак-


Ра

тивних рекурзивних позива генеришу се у инверзном редоследу:


• По завршетку позива (zbir 1), оквир коjи одговара овом позиву укла-
ња се из позивног стека (в. сл. 3.4(д)), а повратна вредност се прослеђу-
jе претходном позиву (zbir 12), што омогућава његово израчунавање
(3 ← (+ 1 2)).
76 3 Рекурзивне функциjе

• По завршетку позива (zbir 12), оквир коjи одговара овом позиву укла-
ња се из стека (в. сл. 3.4(ђ)), а повратна вредност се прослеђуjе
претходном позиву (zbir 123), што омогућава његово израчунавање
(6 ← (+ 3 3)).
• По завршетку позива (zbir 123), оквир коjи одговара овом позиву
уклања се из стека (в. сл. 3.4(е)), а повратна вредност се прослеђуjе
инициjалном позиву (zbir 1234), што омогућава његово израчунавање
(10 ← (+ 6 4))
• Повратна вредност инициjалног позива представља збир цифара ула-
зног аргумента n = 1234. По завршетку овог позива, одговараjући
оквир се уклања из позивног стека, чиме се позивни стек враћа у стање
у коjем jе био пре инициjалног позива (в. сл. 3.4(ж)).
У општем случаjу, ако се функциjи zbir саопшти ненегативни цели
.
броj n коjи се записуjе с d цифара, можемо закључити следеће:
ић
• Функциjа zbir биће позвана тачно d пута.
ов

а.
• Максимални броj оквира коjи ће се у jедном тренутку налазити у по-
ат

ан
зивном стеку jеднак jе d.
Гњ

ж
У наставку ћемо размотрити како се применом тзв. репне рекурзиjе мо-

др
гу редуковати заузети мемориjски простор на позивном стеку и време
ан

извршавања функциjе. за
Репна рекурзиjа jе специjални тип рекурзиjе у коjем команда коjа се
ил

последња извршава у телу функциjе представља рекурзивни позив исте


су
М

функциjе. Тада интерпретатор2 оптимизуjе извршавање функциjе тако


а

што рекурзивни позив функциjе конвертуjе у скок на мемориjску адресу


1.

ав

на коjоj jе функциjа смештена. На нивоу радне мемориjе, то значи да се


02

пр

оквир коjи одговара функциjи у коjоj jе задат репни позив3 уклања из


–2

позивног стека, и замењуjе оквиром коjи одговара функциjи коjа jе реп-


а

но позвана. Другим речима, репна рекурзиjа не доводи до истовременог


20

Св

смештања више оквира на позивном стеку, што jе био случаj илустрован


20

на сл. 3.4.
а.
©

По горњем опису репне рекурзиjе, функциjа приказана на сл. 3.1 ниjе


иj

репно-рекурзивна, jер команда у 4. линиjи поред рекурзивног позива са-


рз

држи и надређену операциjу сабирања. Да бисмо променили дефинициjу


ве

функциjе у репно-рекурзивну, увешћемо додатни улазни аргумент a, коjи


представља збир цифара издвоjених из инициjалног улазног аргумента
на

n до тренутка позива функциjе. Слично као у претходно дефинисаноj


д

функциjи zbir, издваjање цифара из броjа n вршимо од последње цифре


Ра

ка првоj. Међутим, за разлику од функциjе zbir, међузбирови цифара


коjе се издваjаjу из броjа n сукцесивно се прослеђуjу као аргументи ре-
курзивних позива, чиме се уклања потреба за надређеним сабирањем у
последњоj команди функциjе.
2
Или преводилац.
3
Иако овде примарно посматрамо рекурзивне позиве, треба приметити да репни по-
зив, у општем случаjу, не мора бити рекурзиван.
3.2 Рекурзивно издваjање цифара из целих броjева 77

Репно-рекурзивно правило и услов за излазак из рекурзиjе могу се


формално представити на следећи начин:
( n
f (b c, a + (n%10)), n ≥ 10 ,
f (n, a) = 10 (3.10)
n + a, n < 10 ,

при чему jе вредност аргумента a у инициjалном позиву функциjе jеднака


0 (што jе у складу с тим да пре инициjалног позива функциjе ниjедна
цифра jош ниjе издвоjена из n). Илустрациjе ради, вредност f (1234, 0)
рекурзивно се израчунава на следећи начин:

f (123 4 , 0 ) ←− примена рекурзивног правила


= f (12 3 , 4 )
. (3.11)
ић
= f (1 2 , 7 )
=f( 1 , 9 )
ов

а.
ат

ан
= 10 ←− примена услова за излазак из рекурзиjе
Гњ

ж
Дефинициjа репно-рекурзивне функциjе zbir−r, коjа имплементира 4

др
ан

правило (3.2), приказана jе на сл. 3.5. Резултат позивања ове функциjе за


кад jоj се саопшти улазни аргумент n = 1234 приказан jе на сл. 3.6. Функ-
ил

циjа враћа очекивани резултат, исто као и функциjа zbir, али да бисмо
су
М

истакли разлику између извршавања ове две функциjе посматраћемо:


а

• секвенцу рекурзивних позива приликом извршавања ове функциjе кад


1.

ав

jоj се саопшти улазни аргумент n = 1234 (при чему други улазни ар-
02

пр

гумент a ниjе експлицитно наведен, па се примењуjе његова подразу-


–2

мевана вредност 0), приказану на сл. 3.7,


а
20

Св

• секвенцу стања позивног стека за време извршавања ове функциjе,


илустровану на сл. 3.8.
20

а.
©

иj
рз

1 ( define ( z b i r − r n [ a 0 ] )
2 ( i f (< n 1 0 )
ве

3 (+ a n )
4 ( z b i r − r ( q u o t i e n t n 1 0 ) (+ a ( r e m a i n d e r n 1 0 ) ) ) ) )
д на

Слика 3.5 Репно-рекурзивна функциjа коjа за дати ненегативни цели броj израчу-
Ра

нава збир његових цифара.

У општем случаjу, ако се функциjи zbir−r саопшти ненегативни цели


броj n коjи се записуjе с d цифара, можемо закључити следеће:
4
Приметите да улазни аргумент a има подразумевану вредност 0, у складу с правилом
(3.10).
78 3 Рекурзивне функциjе
 
> ( zbir−r 1234)
10
 

Слика 3.6 Резултат позивања функциjе дефинисане на сл. 3.5 кад jоj се саопшти
улазни аргумент n = 1234.

• Функциjа zbir−r биће позвана тачно d пута, исто као и функциjа zbir.
• Приликом сваког репно-рекурзивног позива, оквир стека коjи одговара
функциjи у коjоj jе задат репни позив уклања се из позивног стека,
и замењуjе се оквиром стека коjи одговара функциjи коjа jе репно
позвана. Због тога, броj оквира стека коjи ће се истовремено налазити
у позивном стеку je константан и jеднак 1, за разлику од претходног
.
примера, где jе максимални броj оквира коjи су истовремено смештени
ић
на позивни стек jеднак d (в сл. 3.4 и сл. 3.8). Тиме jе остварена уштеда
ов

мемориjског простора на позивном стеку.

а.
ат

ан
Гњ

ж
( zbir−r 1234) ← (а)
1. позив функциjе

др
( zbir−r 123 4 ) ← (б)
2. позив функциjе
ан

( zbir−r 12 7 ) ← (в)
3. позив функциjе
за
( zbir−r 1 9) ← (г)
4. позив функциjе
ил

10 ← повратак из 4. позива функциjе


су
М

Слика 3.7 Приказ итеративног извршавања функциjе дефинисане на сл. 3.5 кад jоj
1.

ав

се саопшти улазни аргумент n = 1234.


02

пр
–2

а
20

Св
20

ниже адресе ниже адресе ниже адресе ниже адресе


⇑ ⇑ ⇑ ⇑
а.
©

иj
рз

... ... ... ...


ве

... ... ... ...


... ... ... ...
на

( zbir −r 1234 0) ( zbir −r 123 4) ( zbir −r 12 7) ( zbir 1 9)


д
Ра

⇓ ⇓ ⇓ ⇓
више адресе више адресе више адресе више адресе
(а) (б) (в) (г)

Слика 3.8 Илустрациjа стања позивног стека за време итеративног извршавања


функциjе дефинисане на сл. 3.5 кад jоj се саопшти улазни аргумент n = 1234.
3.2 Рекурзивно издваjање цифара из целих броjева 79

3.2.2 Броj цифара ненегативног целог броjа

Пример 3.2. Дефинишимо рекурзивну функциjу коjа израчунава броj ци-


фара датог ненегативнoг целог броjа n.
Jедина разлика у поставци овог примера у односу на поставку примера
3.1 jе та што функциjа треба да израчуна броj цифара, уместо њиховог
збира. Да бисмо решили оваj проблем, довољно jе да изворне ко̂дове дате
на сл. 3.1 и 3.5 променимо тако што ћемо за сваку цифру издвоjену из
броjа n, међузбир увећавати за вредност 1, уместо за вредност издвоjене
цифре. Тако добиjене рекурзивне функциjе приказане су на сл. 3.9 и 3.10.
Мемориjско заузеће позивног стека исто jе као у претходном примеру.

1 ( define ( b r o j − c i f a r a n )
.
ић
2 ( i f (< n 1 0 )
3 1
ов

а.
4 (+ ( b r o j − c i f a r a ( q u o t i e n t n 1 0 ) ) 1 ) ) )
ат

ан
Гњ

ж
Слика 3.9 Рекурзивна функциjа коjа за дати ненегативни цели броj израчунава броj
његових цифара.

др
ан

за
ил

су
М

1 ( define ( b r o j − c i f a r a − r n [ a 0 ] )
а

2 ( i f (< n 1 0 )
1.

ав

3 (+ a 1 )
02

4 ( b r o j − c i f a r a − r ( q u o t i e n t n 1 0 ) (+ a 1 ) ) ) )
пр
–2

а
20

Слика 3.10 Репно-рекурзивна функциjа коjа за дати ненегативни цели броj израчу-
Св

нава броj његових цифара.


20

а.
©

иj
рз
ве

3.2.3 Производ цифара ненегативног целог броjа


на

Пример 3.3. Дефинишимо рекурзивну функциjу коjа израчунава прои-


д

звод цифара датог ненегативнoг целог броjа n.


Ра

Ово jе jош jедна вариjанта проблема представљеног у примеру 3.1 —


jедина разлика jе та што функциjа треба да израчуна производ цифара,
уместо њиховог збира. Jедан начин да решимо оваj проблем jе да изворне
ко̂дове дате на сл. 3.1 и 3.5 променимо тако што ћемо:
• операциjу сабирања (+) заменити операциjом множења (∗),
80 3 Рекурзивне функциjе

• у репно-рекурзивноj функциjи, аргументу a доделити подразумевану


почетну вредност 1, тj., вредност неутралног елемента за операциjу
множења.
Тако добиjене рекурзивне функциjе приказане су на сл. 3.11 и 3.12.

1 ( define ( p r o i z v o d n )
2 ( i f (< n 1 0 )
3 n
4 (∗ ( proizvod ( quotient n 10)) ( remainder n 1 0 ) ) ) )

Слика 3.11 Неоптимизована рекурзивна функциjа коjа за дати ненегативни цели


броj израчунава производ његових цифара.

.
ић
ов

а.
ат

1 ( define ( p r o i z v o d − r n [ a 1 ] )

ан
2 ( i f (< n 1 0 )
Гњ

ж
3 (∗ a n)
4 ( proizvod−r ( q u o t i e n t n 10) (∗ a ( remainder n 1 0 ) ) ) ) )

др
ан

за
Слика 3.12 Неоптимизована репно-рекурзивна функциjа коjа за дати ненегативни
ил

су
цели броj израчунава производ његових цифара.
М

а
1.

ав

Међутим, ове функциjе не представљаjу оптимална рекурзивна реше-


02

ња. У примерима 3.1 и 3.2 било jе неопходно издвоjити све цифре броjа
пр

n. У овом примеру, издваjање свих цифара броjа n неопходно jе само ако


–2

n не садржи цифру 0. У супротном, ако n садржи цифру 0, издваjање


а
20

Св

jе потребно вршити само док се не издвоjи цифра 0 — тада се може за-


20

кључити да ће краjњи производ бити jеднак 0, па нема потребе за даљим


а.

издваjањем цифара (тj., даљим рекурзивним позивима). Због тога ћемо


©

иj

у постоjеће функциjе дате на сл. 3.11 и 3.12 укључити додатни услов за


излазак из рекурзиjе: ако jе издвоjена цифра jеднака 0, секвенца рекур-
рз

зивних позива се прекида, а повратна вредност функциjе jеднака jе 0.


ве

Оптимизоване рекурзивне функциjе приказане су на сл. 3.13 и 3.14.


Резултати позивања функциjа дефинисаних на сл. 3.11, 3.12, 3.13 и
на

3.14, кад им се саопште улазни аргументи n1 = 1234 и n2 = 1204, приказани


д

су на сл. 3.15. Све функциjе враћаjу очекиване резултате, а разлике у


Ра

поступцима израчунавања резултата виде се у секвенцама рекурзивних


позива приказаним на сл. 3.16 и 3.17.
Упоредни подаци о временскоj и просторноj ефикасности ових функ-
циja сумирани су у табели 3.1. Из ове табеле се види да репна рекурзиjа
доводи до тога да jе максимални броj оквира коjи се истовремено налазе
у позивном стеку константан и jеднак 1 (што jе већ обjашњено у примерy
3.2 Рекурзивно издваjање цифара из целих броjева 81

1 ( define ( proizvod − o n )
2 ( cond
3 [ (< n 1 0 ) n ]
4 [ (= ( r e m a i n d e r n 1 0 ) 0 ) 0 ]
5 [ else
6 ( ∗ ( proizvod − o ( q u o t i e n t n 1 0 ) ) ( r e m a i n d e r n 1 0 ) ) ] ) )

Слика 3.13 Оптимизована рекурзивна функциjа коjа за дати ненегативни цели броj
израчунава производ његових цифара.

1 ( define ( p r o i z v o d − r o n [ a 1 ] )
2 ( cond
3 [ (< n 1 0 ) ( ∗ a n ) ]
4 [ (= ( r e m a i n d e r n 1 0 ) 0 ) 0 ]
5 [ else
.
ић
6 ( proizvod−ro ( q u o t i e n t n 10) (∗ a ( remainder n 1 0 ) ) ) ] ) )
ов

а.
Слика 3.14 Оптимизована репно-рекурзивна функциjа коjа за дати ненегативни це-
ат

ан
ли броj израчунава производ његових цифара.
Гњ

ж
др
3.1). Осим тога, приметан jе и додатни ефекат редуковања времена из-
ан

вршавања функциjа, остварен увођењем додатног услова за излазак из


за
ил

рекурзиjе — тj., издваjањем цифара само док се не наиђе на прву цифру


су
М

0.
а
1.

ав

 
02

> ( proizvod 1234)


пр

24
–2

> ( proizvod−r 1234)


а
20

24
Св

> ( proizvod − o 1 2 3 4 )
20

24
а.

> ( proizvod−ro 1234)


©

иj

24
рз

> ( proizvod 1204)


ве

0
> ( proizvod−r 1204)
на

0
> ( proizvod − o 1 2 0 4 )
д

0
Ра

> ( proizvod−ro 1204)


0
 

Слика 3.15 Резултат позивања функциja дефинисаних на сл. 3.11, 3.12, 3.13 и 3.14
кад им се саопште улазни аргументи n1 = 1234 и n2 = 1204.
82 3 Рекурзивне функциjе

( proizvod 1234) ← 1. позив функциjе


(∗ ( proizvod 123) 4) ← 2. позив функциjе
(∗ (∗ ( proizvod 12) 3) 4) ← 3. позив функциjе
(∗ (∗ (∗ ( proizvod 1) 2) 3) 4) ← 4. позив функциjе
(∗ (∗ (∗ 1 2) 3) 4) ← повратак из 4. позива функциjе
(∗ (∗ 2 3) 4) ← повратак из 3. позива функциjе
(∗ 6 4) ← повратак из 2. позива функциjе
24 ← повратак из 1. позива функциjе

( proizvod−r 1234) 1. позив


← функциjе
( proizvod−r 123 4 ) 2. позив
← функциjе
( proizvod−r 12 1 2 ) 3. позив
← функциjе
( proizvod−r 1 24) 4. позив
← функциjе
24 ← повратак из 4. позива функциjе

( proizvod − o 1 2 3 4 ) ← 1. позив функциjе


.
ић
( ∗ ( proizvod − o 1 2 3 ) 4 ) ← 2. позив функциjе
( ∗ ( ∗ ( proizvod − o 1 2 ) 3 ) 4 ) ← 3. позив функциjе
ов
( ∗ ( ∗ ( ∗ ( proizvod − o 1 ) 2 ) 3 ) 4 ) ← 4. позив функциjе

а.
(∗ (∗ (∗ 1 2) 3) 4) ← повратак из 4. позива функциjе
ат

ан
(∗ (∗ 2 3) 4) ← повратак из 3. позива функциjе
Гњ

(∗ 6 4) ← повратак из 2. позива функциjе

ж
24 ← повратак из 1. позива функциjе

др
ан

( proizvod−ro 1234) 1. позив


← за функциjе
( proizvod−ro 123 4 ) 2. позив
← функциjе
ил

( proizvod−ro 12 1 2 ) 3. позив
← функциjе
су

( proizvod−ro 1 24) 4. позив функциjе


М


24 ← повратак из 4. позива функциjе
а
1.

ав
02

пр

Слика 3.16 Приказ извршавања функциjа дефинисаних на сл. 3.11, 3.12, 3.13 и 3.14
кад им се саопшти улазни аргумент n1 = 1234.
–2

а
20

Св

Табела 3.1 Упоредни подаци о временскоj и просторноj ефикасности функциja де-


20

финисаних на сл. 3.11, 3.12, 3.13 и 3.14 кад им се саопште улазни аргументи n1 = 1234
и n2 = 1204.
а.
©

иj

максимални броj оквира


функциjа броj позивања функциje
рз

на позивном стеку
n1 = 1234 n2 = 1204 n1 = 1234 n2 = 1204
ве

proizvod 4 4 4 4
на

proizvod-r 4 4 1 1
proizvod-o 4 2 4 2
д

proizvod-ro 4 2 1 1
Ра
3.2 Рекурзивно издваjање цифара из целих броjева 83

( proizvod 1204) ← 1. позив функциjе


(∗ ( proizvod 120) 4) ← 2. позив функциjе
(∗ (∗ ( proizvod 12) 0) 4) ← 3. позив функциjе
(∗ (∗ (∗ ( proizvod 1) 2) 0) 4) ← 4. позив функциjе
(∗ (∗ (∗ 1 2) 0) 4) ← повратак из 4. позива функциjе
(∗ (∗ 2 0) 4) ← повратак из 3. позива функциjе
(∗ 0 4) ← повратак из 2. позива функциjе
0 ← повратак из 1. позива функциjе

( proizvod−r 1204) 1. позив


← функциjе
( proizvod−r 120 4 ) 2. позив
← функциjе
( proizvod−r 12 0 ) 3. позив
← функциjе
( proizvod−r 1 0) 4. позив
← функциjе
0 ← повратак из 4. позива функциjе

( proizvod − o 1 2 0 4 ) ← 1. позив функциjе


.
ић
( ∗ ( proizvod − o 1 2 0 ) 4 ) ← 2. позив функциjе
(∗ 0 4) ← повратак из 2. позива функциjе
ов
0 ← повратак из 1. позива функциjе

а.
ат

ан
( proizvod−ro 1204) ← 1. позив функциjе
Гњ

( p r o i z v o d − r o 120 4 ) ← 2. позив функциjе

ж
0 ← повратак из 2. позива функциjе

др
ан

за
Слика 3.17 Приказ извршавања функциjа дефинисаних на сл. 3.11, 3.12, 3.13 и 3.14
ил

кад им се саопшти улазни аргумент n2 = 1204.


су
М

а
1.

ав

У претходним примерима, репну рекурзиjу смо користили да бисмо


02

извршавање функциjа учинили ефикасниjим. У следећа два примера по-


пр

казаћемо да се за поjедине проблеме репна рекурзиjа намеће као интуи-


–2

тивно решење.
а
20

Св
20

а.
©

3.2.4 Обртање редоследа цифара у ненегативном


иj

броjу
рз
ве

Пример 3.4. Дефинишимо репно-рекурзивну функциjу коjа прихвата не-


на

негативни цели броj n, и генерише броj коjи се добиjе кад се цифре ула-
зног аргумента напишу у обрнутом редоследу.
д

У овом примеру, репно-рекурзивно правило може се описати на сле-


Ра

дећи начин. Издваjање цифара из броjа n врши се од последње цифре ка


првоj, и свака издвоjена цифра додаjе се — у редоследу издваjања — „на
десни краj” помоћног аргумента a, тj.:
( n
f (b c, a · 10 + (n%10)), n ≥ 10 ,
f (n, a) = 10 (3.12)
a · 10 + n, n < 10 ,
84 3 Рекурзивне функциjе

при чему jе вредност аргумента a у инициjалном позиву функциjе jед-


нака 0. Дефинициjа репно-рекурзивне функциjе коjа имплементира ово
правило приказана jе на сл. 3.18. Резултати позивања функциjе кад jоj
се саопштe изабрани улазни аргументи приказани су на сл. 3.19. Ако се
улазни аргумент n завршава секвенцом нула, оне нису садржане у резул-
туjућоj вредности, што jе очекивано понашање функциjе у овом приме-
ру5 .

1 ( define ( o k r e n i − b r o j − r n [ a 0 ] )
2 ( i f (< n 1 0 )
3 (+ ( ∗ a 1 0 ) n )
4 ( okreni−broj−r ( quotient n 10)
5 (+ ( ∗ a 1 0 ) ( r e m a i n d e r n 1 0 ) ) ) ) )

.
ић
Слика 3.18 Репно-рекурзивна функциjа коjа генерише броj коjи се добиjе кад се
ов

цифре улазног ненегативног целог броjа напишу у обрнутом редоследу.

а.
ат

ан
Гњ

ж
 

др
> ( okreni−broj−r 4)
ан

4
за
ил

> ( okreni−broj−r 1204)


су

4021
М

> ( okreni−broj−r 1230)


а

321
1.

ав

> ( okreni−broj−r 12300000)


02

321
пр

 
–2

а
20

Слика 3.19 Резултати позивања функциjе дефинисане на сл. 3.18 кад jоj се саопштe
Св

изабрани улазни аргументи.


20

а.
©

иj
рз
ве

3.2.5 Проналажење цифре у ненегативном целом


броjу
д на

Пример 3.5. Дефинишимо репно-рекурзивну функциjу коjа проверава да


Ра

ли ненегативни цели броj n садржи цифру c.


У овом примеру, репно-рекурзивно правило може се описати на сле-
дећи начин. Издваjање цифара из броjа n врши се од последње цифре ка
првоj:

5
Проблем коjи захтева очување водећих нула у резултуjућоj вредности посматра се
у задатку 3.3 (у овом поглављу) и примеру 4.19 (у 4. поглављу).
3.3 Рекурзивна обрада монотоних секвенци броjева 85

• све док се први пут не издвоjи цифра c, након чега се прекида секвенца
рекурзивних позива, а функциjа враћа вредност #t,
• или док се не издвоjе и обраде све цифре, што значи да цифра c ниjе
садржана у броjу n, након чега функциjа враћа вредност #f.
Дефинициjа репно-рекурзивне функциjе коjа имплементира ово правило
приказана jе на сл. 3.20. Резултати позивања ове функциjе кад jоj се
саопштe изабрани улазни аргументи приказани су на сл. 3.21.

1 ( define ( s a d r z i ? n c )
2 ( i f (< n 1 0 )
3 ( i f (= n c ) #t #f )
4 ( i f (= ( r e m a i n d e r n 1 0 ) c )
5 #t
6
.
( s a d r z i ? ( quotient n 10) c ) ) ) )
ић
ов

а.
Слика 3.20 Репно-рекурзивна функциjа коjа проверава да ли ненегативни цели броj
ат

ан
n садржи цифру c.
Гњ

ж
др
ан

 
за
> ( sadrzi? 0 0)
ил

#t
су
М

> ( sadrzi? 12345 3 )


#t
а
1.

ав

> ( sadrzi? 12345 1 )


#t
02

пр

> ( sadrzi? 12345 6 )


–2

#f
 
а
20

Св
20

Слика 3.21 Резултати позивања функциjе дефинисане на сл. 3.20 за изабране улазне
аргументе.
а.
©

иj
рз
ве

3.3 Рекурзивна обрада монотоних секвенци броjева


д на
Ра

Уштеда мемориjског простора на позивном стеку остварена применом


репне рекурзиjе у претходним примерима може да делуjе занемарљи-
во. Међутим, такав закључак не важи у општем случаjу. Наредна група
примера односи се на рекурзивну обраду монотоних секвенци броjева,
и у њима ћемо, између осталог, показати да се применом репне рекур-
зиjе може остварити значаjно редуковање мемориjског заузећа позивног
стека.
86 3 Рекурзивне функциjе

3.3.1 Факториjел ненегативног целог броjа

Пример 3.6. Дефинишимо рекурзивну функциjу коjа израчунава факто-


риjел датог ненегативног целог броjа n, тj.:

n · (n − 1) · . . . · 2 · 1, n > 0 ,
f (n) = n! = (3.13)
1, n=0.

Формула (3.13) се може представити рекурзивно:



n · f (n − 1), n > 1 ,
f (n) = (3.14)
1, n≤1,
и репно-рекурзивно:
.
ић

f (n − 1, a · n), n>1,
f (n, a) = (3.15)
ов
a, n≤1,

а.
ат

ан
при чему jе вредност аргумента a у инициjалном позиву функциjе jеднака
Гњ

ж
1 (тj., jеднака вредности неутралног елемента за операциjу множења).
Рекурзивна функциja коjа имплементира формулу (3.14) представље-

др
на jе на сл. 3.22, а њена репно-рекурзивна верзиjа, коjа имплементира
ан

за
формулу (3.15), на сл. 3.23. Кад упоредимо ове две функциjе у односу
ил

на мемориjско заузеће позивног стека, уочава се значаjна разлика. Ако


су
М

се функциjи представљеноj на сл. 3.22 саопшти ненегативни цели броj


а

n, максимални броj оквира коjи ће се у jедном тренутку налазити у по-


1.

ав

зивном стеку jеднак6 jе max{n, 1}. То значи да ће саопштавање довољно


02

пр

великог броjа n овоj функциjи довести до прекорачења капацитета до-


–2

ступне мемориjе и, последично, прекида извршења програма. С друге


а

стране, приликом позивања функциjе представљене на сл. 3.23, макси-


20

Св

мални броj оквира у позивном стеку jе константан и jеднак 1, без обзира


20

на вредност улазног аргумента n ≥ 0.


а.
©

иj
рз

1 ( define ( f a k t o r i j e l n )
2 ( i f (<= n 1 )
ве

3 1
4 ( ∗ n ( f a k t o r i j e l (− n 1 ) ) ) ) )
д на

Слика 3.22 Рекурзивна функциjа коjа израчунава факториjел датог ненегативног


Ра

целог броjа n.

6
Другим речима, ако се функциjи представљеноj на сл. 3.22 саопшти позитивни цели
броj n, максимални броj оквира коjи ће се у jедном тренутку налазити у позивном
стеку jеднак jе n, а ако jоj се саопшти аргумент чиjа jе вредност jеднака 0, у позивни
стек ће бити стављен jедан оквир.
3.3 Рекурзивна обрада монотоних секвенци броjева 87

1 ( define ( f a k t o r i j e l − r n [ a 1 ] )
2 ( i f (<= n 1 )
3 a
4 ( f a k t o r i j e l − r (− n 1 ) ( ∗ n a ) ) ) )

Слика 3.23 Репно-рекурзивна функциjа коjа израчунава факториjел датог ненега-


тивног целог броjа n.

3.3.2 Фибоначиjев низ

Пример 3.7. Нека jе n природни броj. Дефинишимо рекурзивну функциjу


коjа израчунава n-ти елемент Фибоначиjевог низа.
Фибоначиjев низ jе низ у коjем су прва два елемента jеднака 0 и 1,
.
ић
респективно, а сваки следећи елемент jеднак jе збиру два елемента коjа
ов
му непосредно претходе:

а.
ат

ан
0, 1, 1, 2, 3, 5, 8, 13, 21, 34 . . . (3.16)
Гњ

ж
У општем случаjу, n-ти елемент Фибоначиjевог низа може се представити

др
следећом формулом:
ан

за
ил


 0, n = 1,
су

f (n) = 1, n = 2, (3.17)
М

f (n − 1) + f (n − 2), n > 2 .

а
1.

ав

коjа се може компактниjе записати:


02

пр
–2


n − 1, n ≤ 2,
(3.18)
а

f (n) =
20

f (n − 1) + f (n − 2), n>2.
Св
20

Рекурзивна функциjа коjа имплементира формулу (3.18) приказана jе


а.
©

на сл. 3.24. Резултат позивања ове функциjе кад jоj се саопшти улазни
иj

аргумент n = 6 приказан jе на сл. 3.25, а поступак његовог израчунавања


рз

на сл. 3.26. За разлику од претходних примера, у телу функциjе врше се


два рекурзивна позива, па jе приказ поступка израчунавања заснован на
ве

претпоставци да се делови израза коjи се налазе на истом хиjерархиjском


на

нивоу израчунаваjу у редоследу слева-надесно. Нпр., кад се инициjални


позив
д
Ра

( fib 6) (3.19)
развиjе у
(+ (fib 5) ( fib 4))) (3.20)
(в. 2. линиjу на сл. 3.26), прво се у потпуности извршава позив ( fib 5) (в.
линиjе 3.–15.), и тек потом се прелази на извршавање позива ( fib 4) (в.
линиjе 16.–22.). Важно jе приметити да претпоставка о редоследу изра-
88 3 Рекурзивне функциjе

чунавања функциjа на истом хиjерархиjском нивоу не утиче на краjњи


резултат извршавања, и да jе усвоjена с намером да се илуструjе редослед
рекурзивних позива у овом примеру, без губитка општости.

1 ( define ( f i b n )
2 ( i f (<= n 2 )
3 (− n 1 )
4 (+ ( f i b (− n 1 ) ) ( f i b (− n 2 ) ) ) ) )

Слика 3.24 Рекурзивна функциjа коjа израчунава n-ти елемент Фибоначиjевог низа.


. 
ић
> ( f i b 6)
ов
5

а.
 
ат

ан
Слика 3.25 Резултат позивања функциjе дефинисане на сл. 3.24 кад jоj се саопшти
Гњ

ж
улазни аргумент n = 6.

др
ан

за
Приказ извршавања функциjе дат на сл. 3.26 може се посматрати као
ил

хиjерархиjа рекурзивних позива. Интуитивниjи приказ ове хиjерархи-


су
М

jе дат jе на сл. 3.27. Сваки чвор представља по jедан позив функциjе.


Нетерминални чворови, тj., чворови с потомцима, представљаjу позиве
а
1.

ав

функциjе кад jоj се саопште улазни аргументи чиjа jе вредност већа од


02

2. По дефинициjи функциjе датoj на сл. 3.24, у овим позивима изврша-


пр
–2

ваjу се два директно подређена рекурзивна позива, па сви нетерминални


а

чворови имаjу по два директна чвора-потомка коjи одговараjу овим ре-


20

Св

курзивним позивима. Терминални чворови, тj., чворови без потомака,


20

представљаjу позиве функциjе кад jоj се саопште улазни аргументи чиjа


а.
©

jе вредност jеднака 1 или 2.


иj

Важно jе указати на везу између концептуалног приказа поступка из-


рз

вршавања (в. сл. 3.27) и стварног поступка извршавања (в. сл. 3.26).
На концептуалном нивоу, односи између позива функциjе су хиjерархиj-
ве

ски, а приликом извршавања рекурзивни позиви извршаваjу се секвен-


на

циjално. Секвенциjални редослед позивања функциjе коjи произлази из


хиjерархиjског приказа одговара приордер-обиласку хиjерархиjе, коjи jе
д
Ра

представљен испрекиданим усмереним линиjама на сл. 3.28. Ако прати-


мо назначену путању приордер-обиласка, секвенцу стања позивног стека
можемо утврдити на следећи начин:
• за сваки прелаз „одозго-надоле”, тj., са чвора fi на његовог директ-
ног потомка f j , у позивни стек додаjе се оквир коjи одговара позиву
функциjе представљеном чвором f j ,
3.3 Рекурзивна обрада монотоних секвенци броjева 89

1 ( f i b 6)
2 (+ (fib 5) (fib 4) )
3 (+ (+ ( f i b 4 ) ( f i b 3 ) ) ( f i b 4 ) )
4 (+ (+ (+ ( f i b 3 ) ( f i b 2 ) ) ( f i b 3 ) ) ( f i b 4 ) )
5 (+ (+ (+ (+ ( f i b 2 ) ( f i b 1 ) ) ( f i b 2 ) ) ( f i b 3 ) ) ( f i b 4 ) )
6 (+ (+ (+ (+ 1 ( f i b 1 ) ) ( f i b 2 ) ) ( f i b 3 ) ) ( f i b 4 ) )
7 (+ (+ (+ (+ 1 0 ) ( f i b 2 ) ) ( f i b 3 ) ) ( f i b 4 ) )
8 (+ (+ (+ 1 ( f i b 2 ) ) ( f i b 3 ) ) ( f i b 4 ) )
9 (+ (+ (+ 1 1 ) ( f i b 3 ) ) ( f i b 4 ) )
10 (+ (+ 2 ( f i b 3 ) ) ( f i b 4 ) )
11 (+ (+ 2 (+ ( f i b 2 ) ( f i b 1 ) ) ) ( f i b 4 ) )
12 (+ (+ 2 (+ 1 ( f i b 1 ) ) ) ( f i b 4 ) )
13 (+ (+ 2 (+ 1 0 ) ) ( f i b 4 ) )
14 (+ (+ 2 1 ) ( f i b 4 ) )
15 (+ 3 (fib 4) )
16 (+ 3 (+ ( f i b 3 ) ( f i b 2 ) ) )
.
ић
17 (+ 3 (+ (+ ( f i b 2 ) ( f i b 1 ) ) ( f i b 2 ) ) )
18 (+ 3 (+ (+ 1 ( f i b 1 ) ) ( f i b 2 ) ) )
ов
19 (+ 3 (+ (+ 1 0 ) ( f i b 2 ) ) )

а.
20 (+ 3 (+ 1 ( f i b 2 ) ) )
ат

ан
21 (+ 3 (+ 1 1 ) )
Гњ

22 (+ 3 2 )

ж
23 5

др
ан

за
ил

Слика 3.26 Приказ рекурзивног извршавања функциjе дефинисане на сл. 3.24 кад
су
jоj се саопшти улазни аргумент n = 6.
М

(fib 6)
1.

ав
02

пр

(fib 5) (fib 4)
–2

а
20

Св

(fib 4) (fib 3) (fib 3) (fib 2)


20

а.
©

(fib 3) (fib 2) (fib 2) (fib 1) (fib 2) (fib 1)


иj
рз

(fib 2) (fib 1)
ве

Слика 3.27 Хиjерархиjа рекурзивних позива приликом рекурзивног извршавања


на

функциjе дефинисане на сл. 3.24 кад jоj се саопшти улазни аргумент n = 6.


д
Ра
90 3 Рекурзивне функциjе

(fib 6)

(fib 5) (fib 4)

(fib 4) (fib 3) (fib 3) (fib 2)

(fib 3) (fib 2) (fib 2) (fib 1) (fib 2) (fib 1)

(fib 2) (fib 1)

Слика 3.28 Приордер-обилазак хиjерархиjе рекурзивних позива приликом рекур-


зивног извршавања функциjе дефинисане на сл. 3.24 кад jоj се саопшти улазни аргу-
мент n = 6.
.
ић
ов

а.
• за сваки прелаз „одоздо-нагоре”, тj., са чвора f j на његовог директног
ат

ан
претка fi , из позивног стека уклања се оквир коjи одговара позиву
Гњ

функциjе представљеном чвором f j .

ж
др
Резултуjућа секвенца стања позивног стека приказана jе на сл. 3.29.
ан

Максимални броj оквира коjи се истовремено налазе на стеку jеднак jе 5


за
(в. стања (5) и (7) на сл. 3.29). У општем случаjу, за дати улазни аргумент
ил

су

n ≥ 2, максимални броj оквира коjи се истовремено налазе на стеку jеднак


М

jе n − 1 (в. задатак 3.5).


а

Међутим, попуњавање и пражњење позивног стека знатно су динамич-


1.

ав

ниjи него у претходним примерима, а функциjа се вишеструко позива за


02

пр

исте улазне аргументе. Нпр., у посматраном примеру, функциjа се позива


–2

петнаест7 пута, и то:


а
20

Св

• ( fib 6) jеданпут,
20

• ( fib 5) jеданпут,
а.

• ( fib 4) два пута,


©

иj

• ( fib 3) три пута,


рз

• ( fib 2) пет пута,


• ( fib 1) три пута.
ве

Вишеструко израчунавање истих међурезултата представља озбиљни не-


на

достатак ове функциjе. Да бисмо то илустровали, у табели 3.2 дати су


д

броjеви рекурзивних позивања функциjе fib кад jоj се саопште улазни


Ра

аргументи из скупа {1, 2, . . . , 40} (в. задатак 3.6). Подаци из ове табеле
графички су приказани на сл. 3.30. Mоже se уочити експоненциjални раст
броjа рекурзивних позива c(n) у односу на вредност улазног аргумента
n, што ову функциjу чини неефикасном.

7
В. броj чворова у хиjерархиjи рекурзивних позива на сл. 3.27.
3.3 Рекурзивна обрада монотоних секвенци броjева 91

... ... ... ... ... ... ... ...


... ... ... ... ( fib 2) ... ( fib 1) ...
... ... ... ( fib 3) ( fib 3) ( fib 3) ( fib 3) ( fib 3)
... ... ( fib 4) ( fib 4) ( fib 4) ( fib 4) ( fib 4) ( fib 4)
... ( fib 5) ( fib 5) ( fib 5) ( fib 5) ( fib 5) ( fib 5) ( fib 5)
( fib 6) ( fib 6) ( fib 6) ( fib 6) ( fib 6) ( fib 6) ( fib 6) ( fib 6)
... ... ... ... ... ... ... ...
(1) (2) (3) (4) (5) (6) (7) (8)

... ... ... ... ... ... ... ...


... ... ... ... ... ... ... ...
... ( fib 2) ... ... ... ( fib 2) ... ( fib 1)
( fib 4) ( fib 4) ( fib 4) ... ( fib 3) ( fib 3) ( fib 3) ( fib 3)
( fib 5) ( fib 5) ( fib 5) ( fib 5) ( fib 5) ( fib 5) ( fib 5) ( fib 5)
( fib 6) ( fib 6) ( fib 6) ( fib 6) ( fib 6) ( fib 6) ( fib 6) ( fib 6)
... ... ... ... ... ... ... ...
(9) (10) (11) (12) (13) (14) (15) (16)

... ... ... ...


. ... ... ... ...
ић
... ... ... ... ... ... ... ...
... ... ... ... ... ( fib 2) ... ( fib 1)
ов

... ... ...

а.
( fib 3) ( fib 3) ( fib 3) ( fib 3) ( fib 3)
( fib 5) ( fib 5) ... ( fib 4) ( fib 4) ( fib 4) ( fib 4) ( fib 4)
ат

ан
( fib 6) ( fib 6) ( fib 6) ( fib 6) ( fib 6) ( fib 6) ( fib 6) ( fib 6)
... ... ... ... ... ... ... ...
Гњ

ж
(17) (18) (19) (20) (21) (22) (23) (24)

др
ан

... ... ... ... ... ... за


... ... ... ... ... ...
ил

... ... ... ... ... ...


су

( fib 3) ... ( fib 2) ... ... ...


М

( fib 4) ( fib 4) ( fib 4) ( fib 4) ... ...


( fib 6) ( fib 6) ( fib 6) ( fib 6) ( fib 6) ...
а

... ... ... ... ... ...


1.

ав
02

(25) (26) (27) (28) (29) (30)


пр
–2

Слика 3.29 Илустрациjа стања позивног стека за време рекурзивног извршавања


а

функциjе дефинисане на сл. 3.24 кад jоj се саопшти улазни аргумент n = 6.


20

Св
20

Табела 3.2 Броjеви рекурзивних позивања — c(n) — функциjе дефинисане на сл.


а.
©

3.24 кад jоj се саопште улазни аргументи n ∈ {1, 2, . . . , 40}.


иj
рз

n c(n) n c(n) n c(n) n c(n)


1 1 11 177 21 21891 31 2692537
ве

2 1 12 287 22 35421 32 4356617


3 3 13 465 23 57313 33 7049155
на

4 5 14 753 24 92735 34 11405773


д

5 9 15 1219 25 150049 35 18454929


Ра

6 15 16 1973 26 242785 36 29860703


7 25 17 3193 27 392835 37 48315633
8 41 18 5167 28 635621 38 78176337
9 67 19 8361 29 1028457 39 126491971
10 109 20 13529 30 1664079 40 204668309
92 3 Рекурзивне функциjе

·108

1.5
c(n)

0.5

0
.
ић
0 10 20 30 40
ов

а.
n
ат

ан
Слика 3.30 Експоненциjални раст броja рекурзивних позива функциjе дефинисане
Гњ

на сл. 3.24 у односу на вредност улазног аргумента.

ж
др
ан

за
Да бисмо превазишли оваj проблем, дефинисаћемо репно-рекурзивну
ил

функциjу коjа израчунава n-ти елемент Фибоначиjевог низа. У дефини-


су

циjу ове функциjе укључићемо два додатна улазна аргумента коjа памте
М

међурезултате и преносе их у наредне рекурзивне позиве:


а
1.

ав

• a1 — претпоследњи израчунати елемент Фибоначиjевог низа,


02

пр

• a2 — последњи израчунати елемент Фибоначиjевог низа,


–2

а њихове инициjалне вредности одговараjу почетним елементима Фибо-


а
20

Св

начиjевог низа, тj., a1 = 0 и a2 = 1. Репно-рекурзивно правило може се


20

представити на следећи начин:


а.
©


иj

 a1 , n = 1,
f (n, a2 , a1 ) = a2 , n = 2, (3.21)
рз

f (n − 1, a1 + a2 , a2 ), n > 2 ,

ве

Сваким рекурзивним позивом израчунава се нови елемент Фибоначиjевог


на

низа, а вредност аргумента n умањуjе се за jедан.


д

Репно-рекурзивна функциjа коjа имплементира правило (3.21) дефи-


Ра

нисана jе на сл. 3.31. Резултат позивања ове функциjе кад jоj се саопшти
улазни аргумент n = 6 приказан jе на сл. 3.32, а секвенца рекурзивних
позива извршених у поступку израчунавања резултата на сл. 3.33. Функ-
циjа се не позива вишеструко за исте улазне аргументе, а укупни броj
позива jеднак jе 5.
У општем случаjу, за улазни аргумент n ≥ 2:
3.3 Рекурзивна обрада монотоних секвенци броjева 93

• максимални броj оквира коjи се истовремено налазе на позивном стеку


константан jе — и jеднак 1,
• броj рекурзивних позива функциjе jеднак jе n − 1, тj., расте линеарно
у односу на вредност улазног аргумента n, а не експоненциjално, што
ову функциjу чини знатно ефикасниjом од функциjе дефинисане на
сл. 3.24.

1 ( define ( f i b − r n [ a2 1 ] [ a1 0 ] )
2 ( cond
3 [ (= n 1 ) a1 ]
4 [ (= n 2 ) a2 ]
5 [ e l s e ( f i b − r (− n 1 ) (+ a2 a1 ) a2 ) ] ) )

.
ић
Слика 3.31 Репно-рекурзивна функциjа коjа израчунава n-ти елемент Фибоначиjе-
вог низа.
ов

а.
ат

ан
Гњ

ж
 

др
> ( fib−r 6)
5
ан

 
за
ил

су
Слика 3.32 Резултат позивања функциjе дефинисане на сл. 3.31 кад jоj се саопшти
М

улазни аргумент n = 6.
а
1.

ав
02

пр
–2

1 ( fib−r 6)
а
20

2 ( fib−r 5 1 1)
Св

3 ( fib−r 4 2 1)
20

4 ( fib−r 3 3 2)
а.
©

5 ( fib−r 2 5 3)
иj

6 5
рз
ве

Слика 3.33 Приказ итеративног извршавања функциjе дефинисане на сл. 3.31 кад
jоj се саопшти улазни аргумент n = 6.
д на
Ра

3.3.3 Прости броjеви

Пример 3.8. Дефинишимо рекурзивну функциjу коjа проверава да ли jе


дати природни броj n прост. Природни броj jе прост ако jе већи од 1, и
ако jе дељив само броjем 1 и самим собом.
94 3 Рекурзивне функциjе

Претпоставимо да природни броj n ≥ 2 ниjе прост. Тада се може пред-


ставити као производ два природна броjа p и q:

n = pq , (3.22)

за коjе важи 1 < p < n и 1 < q√< n. Притом, jедан од делилаца p и q


мора бити мањи од или jеднак n, jер би, у супротном, важило pq > n.
Другим речима, ако броj n ≥ 2 ниjе прост, бар jедан његов делилац мора
припадати следећоj секвенци узастопних природних броjева:

2, 3, . . . , b nc . (3.23)

Репно-рекурзивно правило за проверу да ли jе дати природни броj n


прост може се описати на следећи начин.
.
ић
• Ако важи n = 1, функциjа враћа вредност #f, jер броj 1, по дефини-
циjи, ниjе прост.
ов

а.
• У супротном, за n ≥ 2, из секвенце (3.23) рекурзивно се издваjаjу бро-
ат

ан
jеви, од наjмањег ка наjвећем:
Гњ

ж
– све док се први пут не издвоjи броj коjи jе делилац броjа n, што зна-

др
чи да броj n ниjе прост, након чега се издваjање броjева из секвенце
ан

прекида, а функциjа враћа вредност #f,


за
– или док се не издвоjе сви броjеви из секвенце, при чему ниjедан од
ил

су

њих ниjе делилац броjа n, што значи да jе броj n прост, након чега
М

функциjа враћа вредност #t.


а
1.

ав

Дефинициjа репно-рекурзивне функциjе коjа имплементира ово пра-


02

вило приказана jе на сл. 3.34. Резултати позивања ове функциjе кад jоj
пр
–2

се саопштe изабрани улазни аргументи дати су на сл. 3.35, а секвенце


а

одговараjућих рекурзивних позива на сл. 3.36.


20

Св
20

а.

1 ( define ( p r o s t ? n [ a 2 ] )
©

иj

2 ( cond
3 [ (= n 1 ) #f ]
рз

4 [ (> ( ∗ a a ) n ) #t ]
ве

5 [ (= ( r e m a i n d e r n a ) 0 ) #f ]
6 [ e l s e ( p r o s t ? n (+ a 1 ) ) ] ) )
д на

Слика 3.34 Репно-рекурзивна функциjа коjа проверава да ли jе природни броj n


Ра

прост.

Иако ова функциjа генерише очекиване вредности, она ниjе оптимал-


на — у сваком рекурзивном позиву ове функциjе проверава се да ли jе
вредност аргумента n jеднака 1 (в. 3. линиjу ко̂да на сл. 3.34), што jе чини
мање ефикасном. Нпр., претпоставимо да jе функциjи саопштен улазни
3.3 Рекурзивна обрада монотоних секвенци броjева 95
 
> ( prost? 31)
#t
> ( prost? 15)
#f
 

Слика 3.35 Резултати позивања функциjе дефинисане на сл. 3.34 кад jоj се саопште
изабрани улазни аргументи.

( prost? 31)
( prost? 31 3 )
( prost? 31 4 )
( prost? 31 5 )
( prost? 31 6 )
#t

.
ић
( prost? 15)
( p r o s t ? 15 3 )
ов

а.
#f
ат

ан
Гњ

ж
Слика 3.36 Приказ итеративног извршавања функциjе дефинисане на сл. 3.34 кад
jоj се саопште изабрани улазни аргументи.

др
ан

за

ил

аргумент n = 541, коjи jе прост броj. Функциjа се позива b 541c = 23


су

пута, тj., по jедном за сваку вредност аргумента a:


М

а
1.

(3.24)
ав

2, 3, . . . , 23, 24 ,
02

пр

и у сваком позиву се проверава да ли jе вредност аргумента n jеднака


–2

1, иако би било довољно ту проверу извршити само jеданпут, приликом


а
20

првог позивања функциjе, jер се вредност аргумента n не мења. Оваj


Св

недостатак можемо превазићи тако што ћемо дефинисати две функциjе,


20

помоћну и главну, при чему:


а.
©

иj

• помоћна функциjа, приказана на сл. 3.37, утврђуjе да ли jе природни


рз

броj n — чиjа jе вредност већа од 1 — прост,


• главна функциjа, такође приказана на сл. 3.37, прво проверава да ли
ве

jе вредност аргумента n jеднака 1 — и ако jесте, враћа вредност #f, а


на

у супротном саопштава улазни аргумент n помоћнoj функциjи.


д

Извршавање главне функциjе кад jоj се саопште изабрани аргументи при-


Ра

казано jе на сл. 3.38.

Функциjе дефинисане на сл. 3.37 називамо, респективно, помоћном и


главном, да бисмо истакли следеће претпоставке:
• помоћнa функциjа позива се у телу главнe функциjе, и ниjе предвиђено
да се позива независно од ње,
96 3 Рекурзивне функциjе

1 ( define ( prost − pom? n [ a 2 ] ) ← помоћна функциjа


2 ( cond
3 [ (> ( ∗ a a ) n ) #t ]
4 [ (= ( r e m a i n d e r n a ) 0 ) #f ]
5 [ e l s e ( prost − pom? n (+ a 1 ) ) ] ) )
6
7 ( define ( p r o s t ? n ) ← главна функциjа
8 ( i f (= n 1 )
9 #f
10 ( prost − pom? n ) ) )

Слика 3.37 Прва верзиjа оптимизоване функциjе коjа проверава да ли jе природни


броj n прост.

( prost? 1)
.
ић
#f
ов

( prost? 31)

а.
( prost − pom? 31)
ат

ан
( prost − pom? 31 3 )
Гњ

ж
( prost − pom? 31 4 )
( prost − pom? 31 5 )

др
( prost − pom? 31 6 )
ан

#t
за
ил

( prost? 15)
су
М

( prost − pom? 1 5 )
( prost − pom? 15 3 )
а
1.

ав

#f
02

пр
–2

Слика 3.38 Приказ итеративног извршавања функциjа дефинисаних на сл. 3.37 и


а

3.39 кад им се саопште изабрани улазни аргументи.


20

Св
20

а.

• корисник увек позива главну функциjу да би утврдио да ли jе дати


©

иj

природни броj n прост, независно од вредности броjа n.


рз

Међутим, у дефинициjама приказаним на сл. 3.37, претпостављени однос


ве

између надређене и подређене функциjе постоjи само у перцепциjи по-


сматрача. Са становишта интерпретатора, обе функциjе дефинисане су
на

глобално, тj., помоћна функциjа се може позивати независно од главне.


д

Ако ниjе предвиђено да се помоћна функциjа позива на другим мести-


Ра

ма у програму, њено засебно дефинисање непотребно оптерећуjе струк-


туру програма, и оставља могућност да функциjа буде позвана у контек-
сту извршавања програма за коjи ниjе предвиђена. Да би се онемогућило
„непредвиђено” позивање помоћне функциjе, потребно jе ограничити њен
лексички опсег (тj., опсег видљивости) на тело главне функциjе. То се
3.3 Рекурзивна обрада монотоних секвенци броjева 97

може8 реализовати угнежђивањем дефинициjе помоћне функциjе у те-


ло главне функциjе, као што jе приказано на сл. 3.39. Тиме jе помоћна
функциjа дефинисана локално9 у односу на главну функциjу, и ниjе ви-
дљива ван ње. Приказ извршавања главне функциje кад jоj се саопште
изабрани улазни аргументи исти jе као и за функциjу дефинисану на сл.
3.37.

1 ( define ( p r o s t ? n ) ← главна функциjа


2 ( define ( prost − pom? n [ a 2 ] ) ← угнежђена помоћна функциjа
3 ( cond
4 [ (> ( ∗ a a ) n ) #t ]
5 [ (= ( r e m a i n d e r n a ) 0 ) #f ]
6 [ e l s e ( prost − pom? n (+ a 1 ) ) ] ) )
7 ( i f (= n 1 )
.
ић
8 #f
9 ( prost − pom? n ) ) )
ов

а.
ат

ан
Слика 3.39 Друга верзиjа оптимизоване функциjе коjа проверава да ли jе природни
броj n прост.
Гњ

ж
др
ан

за
ил

су
М

3.3.4 Наjмањи делилац


а
1.

ав

Пример 3.9. Претпоставимо да jе n природни броj већи од 1. Дефиниши-


02

пр

мо рекурзивну функциjу коjа одређуjе наjмањи нетривиjални делилац


–2

броjа n (тj., наjмањи делилац чиjа jе вредност већа од 1).


а
20

Да бисмо решили оваj проблем, прилагодићемо репно-рекурзивно пра-


Св

вило из претходног примера. За дати природни броj n > 1, из секвенце


20

(3.23) рекурзивно се издваjаjу броjеви, од наjмањег ка наjвећем:


а.
©

иj

• све док се први пут не издвоjи броj a коjи jе делилац броjа n, након чега
рз

се издваjање броjева из секвенце прекида, а функциjа враћа вредност


издвоjеног делиоца a,
ве

• или док се не издвоjе сви броjеви из секвенце, при чему ниjедан од


на

њих ниjе делилац броjа n, што значи да jе броj n прост, након чега
функциjа враћа вредност n.
д
Ра

Дефинициjа репно-рекурзивне функциjе коjа имплементира ово правило


дата jе на сл. 3.40. Извршавање ове функциjе кад jоj се саопште изабрани
улазни аргументи приказано jе на сл. 3.41.

8
У програмском jезику Ракет постоjи више дозвољених синтаксичких структура де-
финициjе локалне функциjе. На сл. 3.39 примењена jе jедна од њих.
9
На истом принципу дефинишу се и локалне променљиве, в. секциjу 2.5 у 2. поглављу.
98 3 Рекурзивне функциjе

1 ( define ( n a j m a n j i − d e l i l a c n [ a 2 ] )
2 ( cond
3 [ (> ( ∗ a a ) n ) n ]
4 [ (= ( r e m a i n d e r n a ) 0 ) a ]
5 [ e l s e ( n a j m a n j i − d e l i l a c n (+ a 1 ) ) ] ) )

Слика 3.40 Репно-рекурзивна функциjа коjа одређуjе наjмањи прости делилац при-
родног броjа n, већег од 1.

( najmanji−delilac 31)
( najmanji−delilac 31 3 )
( najmanji−delilac 31 4 )
( najmanji−delilac 31 5 )
( najmanji−delilac 31 6 )
31
.
ић
( najmanji−delilac 15)
ов

( n a j m a n j i − d e l i l a c 15 3 )

а.
3
ат

ан
Гњ

ж
Слика 3.41 Приказ итеративног извршавања функциjе дефинисане на сл. 3.40 кад

др
jоj се саопште изабрани улазни аргументи.
ан

за
ил

су

3.4 Закључне напомене


М

а
1.

ав

У овом поглављу jе показано да рекурзивне функциjе могу да им-


02

плементираjу две врсте процеса израчунавања резултата: рекурзивне и


пр

итеративне. У општем случаjу, обе врсте процеса подразумеваjу прола-


–2

жење кроз секвенцу стања, али се суштински разликуjу у односу на ди-


а
20

Св

намику мемориjског заузећа приликом моделовања стања процеса. Ста-


20

ња итеративних процеса моделуjу се константним броjем програмских


а.

променљивих, тj., заузеће мемориjског простора приликом извршавања


©

иj

итеративних процеса jе константно. За разлику од тога, приликом моде-


ловања стања рекурзивних процеса, интерпретатор води евиденциjу и о
рз

додатним информациjама коjе нису садржане у програмским променљи-


ве

вама, већ у позивном стеку, а њихова количина ниjе константна, и зависи


од партикуларног редоследа извршавања рекурзивних позива.
на

Важно jе указати на релативно честу концептуалну забуну изазвану


д

неоправданим изjедначавањем поjмова рекурзивне функциjе и рекурзив-


Ра

ног процеса. Ова забуна изазвана jе историjском чињеницом да jе знатни


удео познатих императивних програмских jезика био имплементиран та-
ко да jе процес израчунавања рекурзивне функциjе обавезно био рекур-
зиван, чак и ако jе функциjа била репно-рекурзивна, а за реализовање
итеративних процеса било jе неопходно користити синтаксичке конструк-
3.5 Задаци 99

циjе посебне намене, познатиjе под називом петље 10 . Овакво дизаjнер-


ско ограничење ниjе присутно у функционалним jезицима Ракет и Ским,
коjи извршаваjу репно-рекурзивне функциjе као итеративне процесе с
константним мемориjским заузећем.

Библиографскe напоменe:
• Рекурзивне функциjе у програмском jезику Ским размотрене су
у секциjи „1.2 Procedures and the Processes They Generate” библи-
ографског навода [1].
• Разлике између рекурзивних и итеративних процеса размотрене
су у секциjи „5.1 Designing Register Machines” библиографског на-
вода [1].

.
ић
ов

а.
ат

ан
3.5 Задаци
Гњ

ж
др
Задатак 3.1. Kо̂дови приказани на сл. 3.1 и 3.2 имплементираjу рекур-
ан

за
зивне функциjе коjе израчунаваjу збир цифара датог ненегативног целог
ил

броjа. Проширите приказана решења тако да исправно функционишу и


су

кад им се саопште негативни цели броjеви. (Савет: користите угнежђене


М

помоћне функциjе.)
а
1.

ав

Задатак 3.2. Дефинишите рекурзивну функциjу коjа прихвата стринг,


02

пр

и генерише нови стринг коjи се добиjе кад се симболи улазног аргумента


–2

наведу у обрнутом редоследу, применом:


а
20

Св

а) рекурзивног процеса,
20

б) итеративног процеса (тj., репне рекурзиjе).


а.
©

иj

Задатак 3.3. Дефинишите функциjу коjа прихвата ненегативни цели


броj, и генерише стринг коjи садржи цифре улазног аргумента напи-
рз

сане у обрнутом редоследу. (Савет: упоредите с примером 3.4 — шта се


ве

дешава кад се улазни аргумент завршава секвенцом нула?)


на

Задатак 3.4. а) Дефинишите рекурзивну функциjу коjа одређуjе редно


д

место последњег jављања цифре c у ненегативном целом броjу n. Ако


Ра

броj n не садржи цифру c, повратна вредност функциjе треба да буде


jеднака 0.
б) Проширите решење из тачке а) овог задатка, тако да функциjа
генерише редно место првог jављања цифре c у броjу n.

10
Дефинисање итеративних процеса применом петљи размотрено jе у 6. поглављу.
100 3 Рекурзивне функциjе

Задатак 3.5. Претпоставите да jе функциjи дефинисаноj на сл. 3.24 са-


општен цели броj n ≥ 2 као улазни аргумент. Обjасните зашто jе макси-
мални броj оквира коjи се истовремено налазе на позивном стеку прили-
ком позивања ове функциjе jеднак n − 1.

Задатак 3.6. Дефинишите функциjу коjа за дати природни броj n изра-


чунава броj рекурзивних позивања функциjе дефинисане на сл. 3.24 кад
jоj се саопшти аргумент n (в. табелу 3.2).

Задатак 3.7. Дефинишите рекурзивну функциjу коjа за дати природни


броj n израчунава следећу вредност:

f (n − 1) + f (n − 2) · f (n − 3), n > 3 ,
f (n) = (3.25)
n, n≤3,
.
ић
применом:
ов

а) рекурзивног процеса,

а.
ат

б) итеративног процеса (тj., репне рекурзиjе).

ан
Гњ

ж
др
ан

за
ил

су
М

а
1.

ав
02

пр
–2

а
20

Св
20

а.
©

иj
рз
ве
д на
Ра
Поглавље 4
Рекурзивне структуре података

.
ић
4.1 Увод
ов

а.
ат

ан
У претходном поглављу размотрен jе jедан аспект рекурзиjе — ре-
курзивне функциjе. У овом поглављу посматра се други важни аспект
Гњ

ж
овог концепта — рекурзивне структуре података. За разлику од атом-

др
ских типова података, коjи су до сад били у фокусу пажње, рекурзивне
ан

за
структуре података инхерентно су сложене, тj., представљаjу компози-
ил

циjе атомских типова података. Наjважниjи представник рекурзивних


су

структура података jе листа. У наставку ћемо размотрити рекурзивну


М

дефинициjу листе, основне операциjе над листама и дизаjнирање рекур-


а
1.

ав

зивних функциjа за обраду листи.


02

пр
–2

а
20

4.2 Листа као рекурзивна структура података


Св
20

а.

У математици, уређени пар елемената (x1 , x2 ) дефинише се као скуп у


©

иj

коjем jе x1 декларисан као први елемент, а x2 као други, тj.:


рз

(x1 , x2 ) = {x1 , {x1 , x2 }} . (4.1)


ве

У рачунарскоj мемориjи, уређени пар представља се структуром коjа


на

садржи два показивача1 , при чему:


д

• први показивач садржи мемориjску адресу на коjоj се налази први


Ра

елемент пара,
• други показивач садржи мемориjску адресу на коjоj се налази други
елемент пара,

1
У овом поглављу, показивач ћемо посматрати као мемориjску адресу на коjоj се
налази неки програмски обjекат. Поjам показивача ће бити детаљниjе размотрен у 5.
поглављу.

101
102 4 Рекурзивне структуре података

што jе илустровано графом датим на сл. 4.1. Показивачи су представље-


ни сивим чворовима, елементи пара белим чворовима, а односи између
чворова усмереним гранама.

x2
Слика 4.1 Интерно
представљање уређеног
пара у рачунарскоj мемо- x1
риjи.

Пример 4.1. Дефинисање уређеног пара (1, 2) на програмском jезику Ра-


кет врши се позивањем функциjе cons, коjоj се као улазни аргументи
.
ић
саопштаваjу елементи пара, што jе илустровано на сл. 4.2.
ов

а.
 
ат

ан
> ( cons 1 2 )
’ (1 . 2)
Гњ

ж
 

др
ан

Слика 4.2 Дефинисање уређеног пара (1, 2). за


ил

су
М

Рачунарска имплементациjа допушта и специjални случаj уређеног па-


а

ра, тj., пара коjи садржи само први елемент, док jе други елемент неде-
1.

ав

финисан2 . То значи да показивачу на други елемент ниjе додељена ме-


02

пр

мориjска адреса, што се означава симболичким именом3 null, в. сл. 4.3.


–2

а
20

Св

Слика 4.3 Интерно


20

null
представљање уређеног
а.
©

пара коjи садржи само


иj

први елемент, док jе дру- x1


рз

ги елемент недефинисан.
ве
на

Пример 4.2. Конструисање уређеног пара у коjем jе само први елемент


дефинисан илустровано jе на сл. 4.4.
д
Ра

Полазећи од дефинициjе (4.1), уређена n-торка (x1 , x2 , . . . , xn ) може се


рекурзивно дефинисати као уређени пар, чиjи jе први елемент x1 , а други
елемент (x2 , . . . , xn ), тj.:
2
Интуитивниjа интерпретациjа уређеног пара коjи садржи само први елемент дата
jе у примеру 4.3.
3
Интуитивниjа интерпретациjа симболичког имена null дата jе у примеру 4.7.
4.2 Листа као рекурзивна структура података 103
 
> ( cons 4 n u l l )
’ (4)
 

Слика 4.4 Конструисање уређеног пара у коjем jе само први елемент дефинисан.

(x1 , x2 , . . . , xn ) = (x1 , (x2 , . . . , xn )) . (4.2)

Применом овог рекурзивног правила, уређена n-торка (x1 , x2 , . . . , xn ) може


се разложити на следећи начин:

(x1 , x2 , . . . , xn ) = (x1 , (x2 , x3 , . . . , xn−1 , xn ))


= (x1 , (x2 , (x3 , . . . , xn−1 , xn )))
(4.3)
.
ић
= ...
= (x1 , (x2 , (x3 , . . . , (xn−1 , xn )))) ,
ов

а.
ат

ан
а њено интерно представљање у радноj мемориjи илустровано jе на сл.
4.5. Оваква секвенца рекурзивно угнежђених парова назива се листом.
Гњ

ж
Сваки елемент листе, осим последњег, представљен jе уређеним паром у

др
коjем:
ан

за
• први показивач садржи мемориjску адресу на коjоj се налази елемент
ил

листе,
су
М

• други показивач садржи мемориjску адресу на коjоj се налази уређени


а

пар показивача коjи представља наредни елемент у листи.


1.

ав
02

Последњи елемент листе представљен jе уређеним паром у коjем jе само


пр

први елемент дефинисан.


–2

а
20

Св
20

null
а.
©

иj
рз

x1 x2 xi xn−1 xn
ве

Слика 4.5 Интерно представљање листе као секвенце рекурзивно угнежђених паро-
ва.
д на

Симболички запис листе на програмском jезику Ракет jе:


Ра

’( prvi_element drugi_element ...) , (4.4)

тj., елементи листе се наводе у облим заградама, при чему се испред отво-
рене заграде наводи апостроф. Елементи у листи одваjаjу се празнинама.
104 4 Рекурзивне структуре података

Пример 4.3. Ако се вратимо на пример 4.2, треба приметити да се спе-


циjални случаj уређеног пара с jедним елементом може интуитивниjе
интерпретирати као листа коjа садржи само jедан елемент.

Пример 4.4. Дефинисање листе ’(1 2 3 4) као секвенце рекурзивно угне-


жђених парова приказано jе на сл. 4.6. Други начин да се дефинише иста
листа je позивањем функциjе list, коjоj се као улазни аргументи редом
саопштаваjу елементи листе4 , што jе илустровано на сл. 4.7. Интерно
представљање листе идентично jе у оба случаjа (в. сл. 4.8).

 
> ( cons 1
( cons 2
( cons 3

.
( cons 4 n u l l ) ) ) )
ић
’ (1 2 3 4)
 
ов

а.
ат

Слика 4.6 Дефинисање листе броjева ’(1 2 3 4) као секвенце рекурзивно угнежђе-

ан
них парова.
Гњ

ж
др
ан


за 
ил

> ( l i s t 1 2 3 4)
су

’ (1 2 3 4)
М

 
а
1.

ав

Слика 4.7 Дефинисање листе броjева ’(1 2 3 4) позивањем функциjе list.


02

пр
–2

а
20

Св
20

null
а.
©

иj
рз

1 2 3 4
ве

Слика 4.8 Интерно представљање листе ’(1 2 3 4).


д на

Пример 4.5. Листа може да садржи елементе произвољних типова пода-


Ра

така, укључуjући и угнежђене листе. Нпр., листа:

’((1 "a") (2) #t) , (4.5)


4
Функциjи list се може саопштити произвољни броj улазних аргумената, исто као и
неким функциjама коjе су размотрене у претходним поглављима, в. пример 1.4 у 1.
поглављу, и пример 2.25 у 2. поглављу. У секциjи 4.6 овог поглавља показаћемо како
се дефинишу функциjе коjе прихватаjу произвољни броj улазних аргумената.
4.3 Однос између уређених парова и листи 105

дефинисана на сл. 4.9, садржи три елемента:


• први елемент jе листа ’(1 "a"), коjа садржи два елемента — броj 1 и
стринг "a",
• други елемент jе листа ’(2) , коjа садржи jедан елемент — 2,
• трећи елемент jе буловска вредност #t.
Интерно представљање ове листе илустровано jе на сл. 4.10.

 
> ( l i s t ( l i s t 1 " a " ) ( l i s t 2 ) #t )
’ ( ( 1 " a " ) ( 2 ) #t )
 

Слика 4.9 Дефинисање листе броjева ’((1 "a") (2) #t) позивањем функциjе list.

.
ић
ов

а.
ат

ан
null
Гњ

ж
др
ан

null null #t
за
ил

су
М

1 ”a” 2
а
1.

ав

Слика 4.10 Интерно представљање листе ’((1 "a") (2) #t).


02

пр
–2

а
20

Св
20

4.3 Однос између уређених парова и листи


а.
©

иj

Две основне функциjе над уређеним паровима су:


рз

• car — прихвата уређени пар и враћа његов први елемент,


ве

• cdr — прихвата уређени пар и враћа његов други елемент.


на

Пример 4.6. Издваjање елемената из уређеног пара илустровано jе на сл.


д

4.11.
Ра

Пошто су непразне листе такође уређени парови, могу се саопштити


функциjама car и cdr:
• car прихвата непразну листу и враћа њен први елемент,
• cdr прихвата непразну листу и враћа листу коjа се добиjе кад се из
улазне листе издвоjи први елемент.
106 4 Рекурзивне структуре података
 
> ( define par ( cons 1 2 ) )
> ( car par )
1
> ( cdr par )
2
 

Слика 4.11 Издваjање елемената из уређеног пара.

Пример 4.7. Издваjање елемената из непразне листе илустровано jе на сл.


4.12. Резултат извршавања функциjе cdr кад jоj се саопшти листа коjа
садржи само jедан елемент jе — празна листа (в. сл. 4.13). Симболички
запис празне листе jе ’() .

.
ић
 
> ( define l i s t a ’ (1 2 3 4))
ов

а.
> ( car l i s t a )
ат

ан
> ( cdr l i s t a )
Гњ

ж
’ (2 3 4)
 

др
ан

Слика 4.12 Издваjање елемената из непразне листе.


за
ил

су
М

 
а
1.

ав

> ( define l i s t a ’ (4))


02

> ( car l i s t a )
пр

4
–2

> ( cdr l i s t a )
а
20

’ ()
Св

 
20

а.

Слика 4.13 Резултат извршавања функциjа car и cdr кад им се саопшти листа коjа
©

садржи jедан елемент.


иj
рз

Ако посматрамо интерно представљање уређеног пара с jедним еле-


ве

ментом дато на сл. 4.3, треба приметити да се симболичко име null може
на

интерпретирати као празна листа. На програмском jезику Ракет, празна


листа ’() означава се симболичким именима null и empty (в. сл. 4.14).
д
Ра

Поређење листи и уређених парова може се вршити применом функ-


циjе equal?, описанe у 1. поглављу (в. секциjу 1.6). Основни предикати5
коjи се односе на парове и листе укључуjу:
5
У 1. поглављу (в. секциjу 1.4.1) предикати су дефинисани као функциjе коjе при-
хватаjу jедан улазни аргумент, и утврђуjу да ли припада одређеноj класи података.
Уколико улазни аргумент припада датоj класи података, предикати враћаjу вредност
#t, а у супротном вредност #f.
4.4 Изабране основне функциjе над листама 107
 
> null
’ ()
> empty
’ ()
 

Слика 4.14 Празна листа.

• pair? — утврђуjе да ли jе улазни аргумент уређени пар,


• cons? — утврђуjе да ли jе улазни аргумент уређени пар (исто као пре-
дикат pair?),
• list? — утврђуjе да ли jе улазни аргумент листа,
• empty? — утврђуjе да ли jе улазни аргумент празна листа,
• null? — утврђуjе да ли jе улазни аргумент празна листа (исто као пре-
.
ић
дикат empty?).
ов

а.
Пример 4.8. У табели 4.1 приказане су повратне вредности предиката
ат

ан
кад им се саопште изабрани улазни аргументи. На овом примеру могу се
Гњ

уочити разлике између поjмова уређеног пара и листе.

ж
др
• Листа ниjе специjални случаj уређеног пара: Свака непразна листа
ан

jе, по дефинициjи, уређени пар. Међутим, празна листа (null) ниjе


за
ил

уређени пар.
су

• Уређени пар ниjе специjални случаj листе: У складу са своjом рекур-


М

зивном дефинициjом, листе се jављаjу у две екслузивно дисjунктне


а

форме — празна листа (null) или уређени пар чиjи jе други елемент
1.

ав

листа. Полазећи од ове дефинициjе, може се закључити да уређени


02

пр

пар:
–2

(cons 1 (cons 2 3)) (4.6)


а
20

Св

ниjе листа, док уређени пар:


20

а.

(cons 1 (cons 2 null )) (4.7)


©

иj

jесте листа (в. табелу 4.1), jер jе други елемент наjугнежђениjег пара
рз

jеднак празноj листи.


ве
д на
Ра

4.4 Изабране основне функциjе над листама

У овоj секциjи представљене су изабране основне, унапред дефинисане


функциjе над листама у програмском jезику Ракет. Међутим, да бисмо
илустровали поступак дизаjнирања функциjа над листама, већину пред-
стављених функциjа дефинисаћемо самостално (тj., „од почетка”). При-
мери у наставку овог поглавља разматрани су под претпоставком да jе
108 4 Рекурзивне структуре података

Табела 4.1 Илустрациjа изабраних предиката коjи се односе на уређене парове и


листе.

(cons 1 2) (cons 1 (cons 2 3)) (cons 1 (cons 2 null)) (list 1 2) empty

pair? #t #t #t #t #f
cons? #t #t #t #t #f
list? #f #f #t #t #t
empty? #f #f #f #f #t
null? #f #f #f #f #t

читалац упознат с разликама између рекурзивних и итеративних процеса


израчунавања функциjа, обjашњеним у 3. поглављу.

.
ић
ов

4.4.1 Спаjање листи

а.
ат

ан
Функциjа append прихвата произвољни броj листи, и генерише листу
Гњ

ж
коjа садржи елементе свих саопштених листи, у редоследу навођења. По-

др
ред тога, дозвољено jе да последњи аргумент коjи се саопшти функциjи
ан

буде произвољног типа. У том случаjу, резултата извршавања функциjе


за
ил

append не представља листу — у смислу дефинициjе дате у секциjи 4.2.


су
М

Пример 4.9. Резултати позивања функциjе append кад jоj се саопште иза-
а

брани аргументи приказани су на сл. 4.15.


1.

ав
02

пр
–2

4.4.2 Броj елемената у листи


20

Св
20

Функциjа length прихвата листу, и израчунава броj елемената коjе са-


а.
©

општена листа садржи.


иj
рз

Пример 4.10. Резултати позивања функциjе length кад jоj се саопште иза-
ве

брани аргументи приказани су на сл. 4.16.


Пример 4.11. Дефинишимо функциjу коjа прихвата листу, и израчунава
на

броj елемената коjе саопштена листа садржи.


д

Размотрићемо два решења овог проблема, тj., дефинисаћемо две функ-


Ра

циjе коjе респективно имплементираjу рекурзивни и итеративни процес


израчунавања броjа елемената садржаних у листи. У првом решењу по-
сматрамо рекурзивни процес. Нека jе l листа саопштена функциjи f . Ако
jе l празна листа, функциjа f треба да генерише вредност 0. У супротном,
ако jе l непразна листа коjа садржи n елемената:

’(e0 , e1 , ..., en−1 ) , (4.8)


4.4 Изабране основне функциjе над листама 109
 
> ( append ’ ( 1 2 3 ) ’ ( 4 5 6 ) )
’ (1 2 3 4 5 6)
> ( l i s t ? ( append ’ ( 1 2 3 ) ’ ( 4 5 6 ) ) )
#t
> ( append ’ ( 1 2 ) ’ ( 3 ) ’ ( ) ’ ( 4 5 6 ) )
’ (1 2 3 4 5 6)
> ( l i s t ? ( append ’ ( 1 2 ) ’ ( 3 ) ’ ( ) ’ ( 4 5 6 ) ) )
#t

> ( append ’ ( 1 2 3 ) ’ ( 4 5 ) 6 )
’ (1 2 3 4 5 . 6)
> ( l i s t ? ( append ’ ( 1 2 3 ) ’ ( 4 5 ) 6 ) )
#f
> ( p a i r ? ( append ’ ( 1 2 3 ) ’ ( 4 5 ) 6 ) )
#t
> ( append 1 )
.
ић
1
> ( number? ( append 1 ) )
ов

#t

а.
 
ат

ан
Гњ

Слика 4.15 Резултати позивања функциjе append кад jоj се саопште изабрани аргу-

ж
менти.

др
 
ан

> ( length ’ ( 1 2 3 4 ) )
за
ил

4
су
> ( length ’ ( ( 1 2 ) 3 4 ) )
М

3
а

> ( length ( car ’ ( ( 1 2 ) 3 4 ) ) )


1.

ав

2
02

> ( length ’ ( ) )
пр

0
–2

> ( length 1 ) ← улазни аргумент ниjе листа


а
20

. . . length : c o n t r a c t v i o l a t i o n
Св

expected : l i s t ?
20

given : 1
 
а.
©

иj

Слика 4.16 Резултати позивања функциjе length кад jоj се саопште изабрани аргу-
рз

менти.
ве
на

где jе n ≥ 1, броj њених елемената за jедан jе већи од броjа елемената


садржаних у листи коjа се добиjе кад се из листе l издвоjи први елемент:
д
Ра

f (’( e0 , e1 , ..., en−1 )) = 1 + f (’(e1 , ..., en−1 )) . (4.9)


| {z } | {z }
(cdr l ) (cdr l )

Рекурзивно правило и услов за излазак из секвенце рекурзивних позива


могу се представити обjедињено:
110 4 Рекурзивне структуре података

ако jе l непразна листа ,



1 + f ((cdr l)),
f (l) = (4.10)
0, ако jе l празна листа .

Функциja коjа имплементира рекурзивни процес израчунавања засно-


ван на правилу (4.10) приказана jе на сл. 4.17. Резултати позивања ове
функциjе кад jоj се саопштe изабрани улазни аргументи приказани су на
сл. 4.18, а секвенца рекурзивних позива извршених у поступку израчу-
навања резултата на сл. 4.19.

1 ( define ( d u z i n a l )
2 ( i f ( empty? l )
3 0
4 (+ 1 ( d u z i n a ( cdr l ) ) ) ) )

.
ић
Слика 4.17 Рекурзивна функциjа коjа израчунава броj елемената у листи.
ов

а.
ат

ан
Гњ

ж
 

др
> ( duzina ’ (1 2 3 4))
ан

4
за
> ( duzina ’ ((1 2) 3 4))
ил

3
су

> ( d u z i n a ( car ’ ( ( 1 2 ) 3 4 ) ) )
М

2
а

> ( duzina ’ ( ) )
1.

ав

0
02

пр

> ( duzina 1) ← улазни аргумент ниjе листа


–2

. . . cdr : c o n t r a c t v i o l a t i o n
а

expected : pair?
20

Св

given : 1
 
20

а.
©

Слика 4.18 Резултати позивања функциjе дефинисане на сл. 4.17 кад jоj се саопште
иj

изабрани улазни аргументи.


рз
ве

У другом решењу посматрамо итеративни процес израчунавања броjа


елемената садржаних у листи. Издваjање елемената из листе l врши се
на

од првог елемента листе ка последњем, и за сваки издвоjени елемент,


д

вредност помоћног аргумента a увећава се за 1. Кад се из листе издвоjе


Ра

сви елементи, вредност помоћног аргумента a jеднака jе броjу елемената


у листи. Ово правило се може формулисати:

f ((cdr l), a + 1), ако jе l непразна листа ,



f (l, a) = (4.11)
a, ако jе l празна листа ,
4.4 Изабране основне функциjе над листама 111

1 ( duzina ’ ((1 2) 3 4))


2 (+ 1 ( d u z i n a ’ ( 3 4 ) ) )
3 (+ 1 (+ 1 ( d u z i n a ’ ( 4 ) ) ) )
4 (+ 1 (+ 1 (+ 1 ( d u z i n a ’ ( ) ) ) ) )
5 (+ 1 (+ 1 (+ 1 0 ) ) )
6 (+ 1 (+ 1 1 ) )
7 (+ 1 2 )
8 3

Слика 4.19 Приказ рекурзивног извршавања функциjе дефинисане на сл. 4.17 кад
jоj се саопшти изабрани улазни аргумент.

при чему jе вредност аргумента a у инициjалном позиву функциjе jедна-


ка 0 (што jе у складу с тим да пре инициjалног позива функциjе ниjедан
.
ић
елемент ниjе издвоjен из листе).
ов
Репно-рекурзивна функциja коjа имплементира итеративни процес за-

а.
снован на правилу (4.11) приказана jе на сл. 4.20. Резултати позивања ове
ат

ан
функциjе кад jоj се саопштe изабрани улазни аргументи jеднаки су ре-
Гњ

ж
зултатима позивања претходно дефинисане функциjе коjа имплементира

др
рекурзивни процес — в. сл. 4.18 — и нису приказани засебно. Међутим,
ан

секвенца рекурзивних позива извршених у итеративном процесу разли-


за
куjе се од претходног решења, и приказана jе на сл. 4.21.
ил

су
М

1 ( define ( duzina − r l [ a 0 ] )
1.

ав

2 ( i f ( empty? l )
02

3 a
пр

4 ( duzina − r ( cdr l ) (+ a 1 ) ) ) )
–2

а
20

Св

Слика 4.20 Репно-рекурзивна функциjа коjа израчунава броj елемената у листи.


20

а.
©

иj
рз

1 ( duzina − r ’ ((1 2) 3 4))


ве

2 ( duzina − r ’ (3 4) 1)
3 ( duzina − r ’ (4) 2)
на

4 ( duzina − r ’ ( ) 3)
5 3
д
Ра

Слика 4.21 Приказ итеративног извршавања функциjе дефинисане на сл. 4.20 кад
jоj се саопшти изабрани улазни аргумент.
112 4 Рекурзивне структуре података

4.4.3 Читање елемената листе на основу индекса

Сваком елементу непразне листе додељуjе се индекс коjи означава по-


зициjу елемента у листи. Првом елементу у листи додељуjе се индекс 0,
другом елементу индекс 1, итд. — елементу коjи се налази на i-том месту
додељуjе се индекс i − 1.
Функциjа list-ref прихвата листу l и ненегативни цели броj n, и враћа
елемент листе l коjем jе додељен индекс n.

Пример 4.12. Резултати позивања функциjе list-ref кад jоj се саопште иза-
брани аргументи приказани су на сл. 4.22.

 
> ( list−ref ’ ((1 2) 3 4) 0)
.
ић
’ (1 2)
> ( list−ref ’ ((1 2) 3 4) 1)
ов

а.
3
ат

> ( list−ref ’ ((1 2) 3 4) 2)

ан
4
Гњ

ж
> ( list−ref ’ ((1 2) 3 4) 3) ← индекс ван опсега листе
. . . list−ref : index too l a r g e f o r l i s t

др
index : 3
ан

in : ’ ((1 2) 3 4)
за
 
ил

су
М

Слика 4.22 Резултати позивања функциjе list-ref кад jоj се саопште изабрани аргу-
а

менти.
1.

ав
02

пр
–2

Пример 4.13. Дефинишимо функциjу коjа прихвата листу l и ненегатив-


а

ни цели броj n, и враћа елемент листе l коjем jе додељен индекс n.


20

Св

Ако jе вредност индекса n jеднака 0, функциjа треба да врати пр-


20

ви елемент листе — (car l). У супротном, ако jе n > 0, елемент коjем jе


а.
©

додељен индекс n у листи l може се реферисати као елемент коjем jе


иj

додељен индекс n − 1 у листи коjа се добиjе кад се из l уклони први еле-


рз

мент, тj. у листи (cdr l). На основу тога, можемо формулисати следеће
ве

репно-рекурзивно правило:
на

(car l),

n=0,
f (l, n) = (4.12)
f ((cdr l), n − 1), n > 0 .
д
Ра

Репно-рекурзивна функциjа коjа имплементира правило (4.12) прика-


зана jе на сл. 4.23. Резултати позивања ове функциjе кад jоj се саопштe
изабрани улазни аргументи приказани су на сл. 4.24, а секвенца рекур-
зивних позива извршених у поступку израчунавања резултата на сл. 4.25.
4.4 Изабране основне функциjе над листама 113

1 ( define ( i n d e k s l n )
2 ( i f (= n 0 )
3 ( car l )
4 ( i n d e k s ( cdr l ) (− n 1 ) ) ) )

Слика 4.23 Репно-рекурзивна функциjа коjа враћа елемент листе l коjем jе додељен
индекс n.
 
> ( indeks ’ ((1 2) 3 4) 0)
’ (1 2)
> ( indeks ’ ((1 2) 3 4) 1)
3
> ( indeks ’ ((1 2) 3 4) 2)
4
> ( indeks ’ ((1 2) 3 4) 3) ← индекс ван опсега листе
.
ић
. . car : c o n t r a c t violation
expected : pair?
ов

а.
given : ’ ()
 
ат

ан
Гњ

ж
Слика 4.24 Резултати позивања функциjе дефинисане на сл. 4.23 кад jоj се саопште
изабрани улазни аргументи.

др
ан

1 ( indeks ’ ((1 2) 3 4) 2)
за
ил

2 ( indeks ’ (3 4) 1)
су

3 ( indeks ’ (4) 0)
М

4 4
а
1.

ав
02

Слика 4.25 Приказ итеративног извршавања функциjе дефинисане на сл. 4.23 кад
пр

jоj се саопшти изабрани улазни аргумент.


–2

а
20

Св
20

4.4.4 Префикс листе


а.
©

иj

Функциjа take прихвата листу l и ненегативни цели броj k, и враћа


рз

нову листу коjа садржи првих k елемената листе l.


ве

Пример 4.14. Резултати позивања функциjе take кад jоj се саопште иза-
брани аргументи приказани су на сл. 4.26.
д на

Пример 4.15. Дефинишимо функциjу коjа прихвата листу l и ненегатив-


Ра

ни цели броj k, и враћа нову листу коjа садржи првих k елемената листе
l.
И у овом примеру ћемо размотрити два решења, тj., дефинисаћемо
две функциjе коjе респективно имплементираjу рекурзивни и итератив-
ни процес израчунавања тражених резултата. У првом решењу посма-
трамо рекурзивни процес. Ако jе вредност улазног аргумента k jеднака
0, функциjа треба да генерише празну листу — empty. У супротном, ако
114 4 Рекурзивне структуре података
 
> ( take ’ ( ( 1 2 ) 3 4 ) 0 )
’ ()
> ( take ’ ( ( 1 2 ) 3 4 ) 1 )
’ ((1 2))
> ( take ’ ( ( 1 2 ) 3 4 ) 2 )
’ ((1 2) 3)
> ( take ’ ( ( 1 2 ) 3 4 ) 3 )
’ ((1 2) 3 4)
> ( take ’ ( ( 1 2 ) 3 4 ) 4 ) ← вредност k ван опсега листе
. . . take : c o n t r a c t v i o l a t i o n
e x p e c t e d : a l i s t with a t l e a s t 4 e l e m e n t s
given : ’ ((1 2) 3 4)
 

Слика 4.26 Резултати позивања функциjе take кад jоj се саопште изабрани аргу-
менти.
.
ић
ов

jе k > 0, резултат позивања функциjе за непразну листу l коjа садржи n

а.
ат

елемената:

ан
’(e0 , e1 , ..., en−1 ) , (4.13)
Гњ

ж
др
где jе n ≥ 1, може се представити уређеним паром6 у коjем jе:
ан

• први елемент пара jеднак првом елементу листе l,


за
ил

• други елемент пара jеднак листи коjа садржи првих k − 1 елемeната


су

из листе (cdr l),


М

тj.:
1.

ав
02

(4.14)
пр

f (’( e0 , e1 , ..., en−1 ), k) = (cons e0 f (’(e1 , ..., en−1 ), k − 1)) .


–2

| {z } |{z} | {z }
(cdr l ) 1. елемент (cdr l )
а
20

Св

| {z }
пара 2. елемент пара
20

Рекурзивно правило и услов за излазак из секвенце рекурзивних по-


а.
©

зива могу се представити обjедињено:


иj
рз

(cons (car l) f ((cdr l),k − 1)), k > 0 ,



f (l, k) = (4.15)
ве

empty, k=0.
на

Функциja коjа имплементира рекурзивни процес израчунавања засно-


ван на правилу (4.15) приказана jе на сл. 4.27. Резултати позивања ове
д

функциjе кад jоj се саопштe изабрани улазни аргументи приказани су на


Ра

сл. 4.28, а секвенца рекурзивних позива извршених у поступку израчу-


навања резултата на сл. 4.29.
У другом решењу посматрамо итеративни процес израчунавања тра-
жених резултата. Издваjање елемената из листе l врши се од првог еле-
6
Оваj уређени пар представља листу, jер jе његов други елемент спецификован као
листа.
4.4 Изабране основне функциjе над листама 115

1 ( define ( p r e f i k s l k )
2 ( i f (= k 0 )
3 empty
4 ( cons ( car l ) ( p r e f i k s ( cdr l ) (− k 1 ) ) ) ) )

Слика 4.27 Рекурзивна функциjа коjа прихвата листу l и ненегативни цели броj k,
и враћа нову листу коjа садржи првих n елемената листе k.
 
> ( p r e f i k s ’ ((1 2) 3 4) 0)
’ ()
> ( p r e f i k s ’ ((1 2) 3 4) 1)
’ ((1 2))
> ( p r e f i k s ’ ((1 2) 3 4) 2)
’ ((1 2) 3)
> ( p r e f i k s ’ ((1 2) 3 4) 3)
.
ић
’ ((1 2) 3 4)
> ( p r e f i k s ’ ((1 2) 3 4) 4) ← вредност k ван опсега листе
ов

а.
. . . car : c o n t r a c t v i o l a t i o n
ат

expected : pair?

ан
given : ’ ()
Гњ

 

ж
др
Слика 4.28 Резултати позивања функциjе дефинисане на сл. 4.27 кад jоj се саопште
ан

изабрани улазни аргументи.


за
ил

су

1 ( p r e f i k s ’ ((1 2) 3 4) 2)
М

2 ( cons ’ ( 1 2 ) ( p r e f i k s ’ ( 3 4 ) 1 ) )
а

3 ( cons ’ ( 1 2 ) ( cons 3 ( p r e f i k s ’ ( 4 ) 0 ) ) )
1.

ав

4 ( cons ’ ( 1 2 ) ( cons 3 empty ) )


02

пр

5 ( cons ’ ( 1 2 ) ’ ( 3 ) )
6 ’ ((1 2) 3)
–2

а
20

Св

Слика 4.29 Приказ рекурзивног извршавања функциjе дефинисане на сл. 4.27 кад
20

jоj се саопшти изабрани улазни аргумент.


а.
©

иj
рз

мента листе ка последњем, и сваки издвоjени елемент додаjе се на краj


помоћнe листе a, тj.:
ве

f (’ ( ei , ei+1 , ..., en−1 ), k, ’ (e0 , e1 , ..., ei−1 ))


на

| {z } | {z }
д

листа l листа a
(4.16)
Ра

= f (’ (ei+1 , ..., en−1 ), k − 1, ’ (e0 , e1 , ..., ei−1 , ei ))


| {z } | {z }
(cdr l) (append a (list (car l)))

Кад се у помоћну листу a издвоjи првих k елемената листе l, изврша-


вање функциjе се завршава, а функциjа враћа листу a као резултат. Ово
правило може се формулисати:
116 4 Рекурзивне структуре података

f ((cdr l), k − 1, (append a (list (car l)))), k>0,
f (l, k, a) = (4.17)
a, k=0,

при чему jе вредност улазног аргумента a у инициjалном позиву функциjе


jеднака празноj листи (што jе у складу с тим да пре инициjалног позива
функциjе ниjедан елемент ниjе издвоjен из листе).
Репно-рекурзивна функциja коjа имплементира итеративни процес за-
снован на формули (4.17) приказана jе на сл. 4.30. Резултати позивања
ове функциjе кад jоj се саопштe изабрани улазни аргументи jеднаки су
резултатима позивања претходно дефинисане функциjе коjа имплемен-
тира рекурзивни процес (в. сл. 4.28), a секвенца рекурзивних позива из-
вршених у поступку израчунавања резултата приказана jе на сл. 4.31.

1
.
( define ( p r e f i k s − r l k [ l 1 empty ] )
ић
2 ( i f (= k 0 )
ов
3 l1

а.
4 ( p r e f i k s − r ( cdr l ) (− k 1 ) ( append l 1 ( l i s t ( car l ) ) ) ) ) )
ат

ан
Гњ

ж
Слика 4.30 Репно-рекурзивна функциjа коjа прихвата листу l и ненегативни цели

др
броj k, и враћа нову листу коjа садржи првих n елемената листе k.
ан

за
ил

су
М

1 ( prefiks−r ’ ((1 2) 3 4) 2)
а

2 ( prefiks−r ’ (3 4) 1 ’ ((1 2 ) ) )
1.

ав

3 ( prefiks−r ’ (4) 0 ’ ((1 2) 3))


02

пр

4 ’ ((1 2) 3)
–2

а
20

Св

Слика 4.31 Приказ итеративног извршавања функциjе дефинисане на сл. 4.30 кад
jоj се саопшти изабрани улазни аргумент.
20

а.
©

иj

Треба приметити разлику између рекурзивног процеса дефинисаног


рз

на сл. 4.27, и итеративног процеса дефинисаног на сл. 4.30. Иако се у оба


процеса елементи улазне листе издваjаjу од првог елемента ка послед-
ве

њем, редоследи додавања издвоjених елемената у резултуjућу листу се


на

разликуjу. У рекурзивном процесу, сваки издвоjени елемент се применом


функциjе cons додаjе на почетак текуће листе, тj., резултуjућа листа се
д
Ра

попуњава од k-тог елемента улазне листе ка првом елементу. За разлику


од тога, у итеративном процесу, сваки издвоjени елемент се применом
функциjе append додаjе на краj текуће листе, тj., резултуjућа листа се
попуњава од првог елемента улазне листе ка k-том елементу. Ова разлика
jе илустрована на сл. 4.32.
4.4 Изабране основне функциjе над листама 117

1 ( p r e f i k s ’ (1 2 3 4 5) 3) ← рекурзивни процес
2 ( cons 1 ( p r e f i k s ’ ( 2 3 4 5 ) 2 ) )
3 ( cons 1 ( cons 2 ( p r e f i k s ’ ( 3 4 5 ) 1 ) ) )
4 ( cons 1 ( cons 2 ( cons 3 ( p r e f i k s ’ ( 4 5 ) 0 ) ) ) )
5 ( cons 1 ( cons 2 ( cons 3 empty ) ) )
6 ( cons 1 ( cons 2 ’(3) ) )
7 ( cons 1 ’(2 3) )
8 ’(1 2 3)
9
10 ( p r e f i k s − r ’ ( 1 2 3 4 5 ) 3 empty ) ← итеративни процес
11 ( p r e f i k s − r ’ ( 2 3 4 5 ) 2 ’(1) )
12 ( p r e f i k s − r ’ ( 3 4 5 ) 1 ’(1 2) )
13 ( p r e f i k s − r ’ ( 4 5 ) 0 ’(1 2 3) )
14 ’(1 2 3)

.
ић
Слика 4.32 Упоредни приказ генерисања резултуjуће листе у рекурзивном процесу
дефинисаном на сл. 4.27, и итеративном процесу дефинисаном на сл. 4.30, за изабране
ов

а.
улазне аргументе.
ат

ан
Гњ

ж
4.4.5 Суфикс листе

др
ан

Функциjа drop прихвата листу l и ненегативни цели броj k, и враћа


за
ил

листу коjа се добиjе кад се из улазне листе уклони првих k елемената.


су
М

Пример 4.16. Резултати позивања функциjе drop кад jоj се саопште иза-
а

брани аргументи приказани су на сл. 4.33.


1.

ав
02

пр

 
–2

> ( drop ’ ( ( 1 2 ) 3 4 ) 0 )
а

’ ((1 2) 3 4)
20

Св

> ( drop ’ ( ( 1 2 ) 3 4 ) 1 )
20

’ (3 4)
а.

> ( drop ’ ( ( 1 2 ) 3 4 ) 2 )
©

’ (4)
иj

> ( drop ’ ( ( 1 2 ) 3 4 ) 3 )
рз

’ ()
> ( drop ’ ( ( 1 2 ) 3 4 ) 4 ) ← вредност k ван опсега листе
ве

. . . drop : c o n t r a c t v i o l a t i o n
e x p e c t e d : a l i s t with a t l e a s t 4 e l e m e n t s
на

given : ’ ((1 2) 3 4)
 
д
Ра

Слика 4.33 Резултати позивања функциjе drop кад jоj се саопште изабрани аргу-
менти.

Пример 4.17. Дефинишимо функциjу коjа прихвата листу l и ненегатив-


ни цели броj k, и враћа листу коjа се добиjе кад се из улазне листе уклони
првих k елемената.
118 4 Рекурзивне структуре података

У овом примеру, репна рекурзиjа се намеће као интуитивно решење.


Издваjање елемената из листе l врши се од првог елемента листе ка по-
следњем, а кад се издвоjи првих k елемената, извршавање функциjе се
завршава, а функциjа враћа преостали део улазне листе као резултат.
Ово правило може се формулисати:

f ((cdr l), k − 1), k > 0 ,
f (l, k) = (4.18)
l, k=0.

Репно-рекурзивна функциja коjа имплементира итеративни процес за-


снован на правилу (4.18) приказана jе на сл. 4.34. Резултати позивања
ове функциjе кад jоj се саопштe изабрани улазни аргументи приказа-
ни су на сл. 4.35, а секвенца рекурзивних позива извршених у поступку
израчунавања резултата на сл. 4.36.
.
ић
ов

1 ( define ( s u f i k s l k )

а.
2 ( i f (= k 0 )
ат

ан
3 l
Гњ

ж
4 ( s u f i k s ( cdr l ) (− k 1 ) ) ) )

др
ан

Слика 4.34 Рекурзивна функциjа коjа прихвата листу l и ненегативни цели броj k,
за
и враћа листу коjа се добиjе кад се из улазне листе уклони првих k елемената.
ил

су
М

а
1.

ав

 
02

> ( s u f i k s ’ ((1 2) 3 4) 0)
пр

’ ((1 2) 3 4)
–2

> ( s u f i k s ’ ((1 2) 3 4) 1)
а
20

’ (3 4)
Св

> ( s u f i k s ’ ((1 2) 3 4) 2)
20

’ (4)
а.

> ( s u f i k s ’ ((1 2) 3 4) 3)
©

’ ()
иj

> ( s u f i k s ’ ((1 2) 3 4) 4) ← вредност k ван опсега листе


рз

. . cdr : c o n t r a c t violation
ве

expected : pair?
given : ’ ()
 
д на

Слика 4.35 Резултати позивања функциjе дефинисане на сл. 4.34 кад jоj се саопште
Ра

изабрани улазни аргументи.


4.4 Изабране основне функциjе над листама 119

1 ( s u f i k s ’ ((1 2) 3 4) 2)
2 ( s u f i k s ’ (3 4) 1)
3 ( s u f i k s ’ (4) 0)
4 ’ (4)

Слика 4.36 Приказ итеративног извршавања функциjе дефинисане на сл. 4.34 кад
jоj се саопштe изабрани улазни аргументи.

4.4.6 Обртање редоследа елемената у листи

Функциjа reverse прихвата листу l, и генерише листу коjа има исте


елементе као улазна листа, али наведене у обрнутом редоследу.

.
Пример 4.18. Резултати позивања функциjе reverse кад jоj се саопште
ић
изабрани аргументи приказани су на сл. 4.37. Може се приметити да
ов

функциjа reverse не мења редослед елемената у угнежђеним листама.

а.
ат

ан
 
Гњ

ж
> ( r e v e r s e ’ (1 2 3 4))

др
’ (4 3 2 1)
> ( reverse ’ ())
ан

’ ()
за
ил

> ( r e v e r s e ’ (1 (2 3) 4))
су

’ (4 (2 3) 1) ← редослед елемената у листи ’(2 3) jе непромењен


М

 
а
1.

ав

Слика 4.37 Резултати позивања функциjе reverse кад jоj се саопште изабрани аргу-
02

менти.
пр
–2

а
20

Св

Пример 4.19. Дефинишимо функциjу коjа прихвата листу l, и генерише


листу коjа има исте елементе као улазна листа, али наведене у обрнутом
20

редоследу, при чему jе потребно променити редослед елемената и у свим


а.
©

угнежђеним листама.
иj

Функциjа спецификована у овом примеру сложениjа jе од функциjе


рз

reverse, jер се захтева промена редоследа не само у надређеноj листи, већ


ве

и у свим угнежђеним листама. Посматраћемо два решења коjа респек-


тивно имплементираjу рекурзивни и итеративни процес.
на

(i) Дефинисање рекурзивног процеса. Дефинисање функциjе коjа им-


д

плементира рекурзивни процес извешћемо у два корака. У првом кораку


Ра

дефинисаћемо непотпуно решење, тj., функциjу коjа обрће редослед еле-


мената само у надређеноj листи, али не и у угнежђеним листама (исто
као функциjа reverse). Проширивањем овог непотпуног решења, у другом
кораку дефинисаћемо тражену функциjу.
Да бисмо илустровали рекурзивни процес, кренимо од поjедноставље-
ног контекста, и посматраjмо jедну партикуларну вредност улазног ар-
гумента. Нека jе улазна листа ’(1 2 3 4). Очекивана вредност функциjе
120 4 Рекурзивне структуре података

кад jоj се саопшти оваj улазни аргумент jе:

f (’(1 2 3 4)) = ’(4 3 2 1) . (4.19)

Поступак израчунавања може се рекурзивно представити на следећи на-


чин:
f (’( 1 2 3 4)) = ’(4 3 2 1)
= (append ’(4 3 2) ’( 1 )) (4.20)
= (append f (’(2 3 4)) ’( 1 )) .

У општем случаjу, резултат обртања редоследа елемената у непразноj


листи:
l = ’(e0 , e1 , ..., en−1 ) , (4.21)
.
ић
где jе n ≥ 1, може се представити као спаjање:
ов

• листe коjа се генерише обртањем редоследа елемената листе ’(e1 , ..., en−1 )

а.
ат

— добиjене издваjањем првог елемента из улазне листе l,

ан
• с листом коjа садржи само први елемент улазне листе l — ’(e0 ),
Гњ

ж
тj.:

др
ан

за
f (’ ( e0 , e1 , ..., en−1 )) = (append f (’ (e1 , ..., en−1 )) ’( e0 ) ) . (4.22)
ил

| {z } | {z } | {z }
су
l (cdr l) (list (car l))
М

У сваком рекурзивном позиву функциjе, из листе се издваjа по jедан


а
1.

ав

елемент, све док се не издвоjе сви елементи, а рекурзивно правило, обjе-


02

дињено с условом за излазак из рекурзиjе, гласи:


пр
–2

(append f ((cdr l)) (list (car l))), ако jе l непразна листа ,



а
20

f (l) =
Св

empty, ако jе l празна листа .


20

(4.23)
а.
©

иj

Функциja коjа имплементира рекурзивни процес заснован на правилу


(4.23) приказана jе на сл. 4.38. Резултати позивања ове функциjе кад jоj се
рз

саопштe изабрани улазни аргументи приказани су на сл. 4.39, а секвенца


ве

рекурзивних позива извршених у поступку израчунавања резултата на


сл. 4.40.
д на
Ра

1 ( define ( o k r e n i l )
2 ( cond
3 [ ( empty? l ) empty ]
4 [ e l s e ( append ( o k r e n i ( cdr l ) ) ( l i s t ( car l ) ) ) ] ) )

Слика 4.38 Непотпуна рекурзивна функциjа коjа обрће редослед елемената у листи.
4.4 Изабране основне функциjе над листама 121
 
> ( okreni ’ (1 2 3 4))
’ (4 3 2 1)
> ( okreni ’ ())
’ ()
> ( okreni ’ (1 (2 3) 4))
’ (4 (2 3) 1) ← редослед елемената у листи ’(2 3) jе непромењен
 

Слика 4.39 Резултати позивања функциjе дефинисане на сл. 4.38 кад jоj се саопште
изабрани улазни аргументи.

1 ( okreni ’ (1 (2 3) 4))
2 ( append ( o k r e n i ’ ( ( 2 3 ) 4 ) ) ’ ( 1 ) )
3 ( append ( append ( o k r e n i ’ ( 4 ) ) ’ ( ( 2 3 ) ) ) ’ ( 1 ) )
4 ( append ( append ( append ( o k r e n i ’ ( ) ) ’ ( 4 ) ) ’ ( ( 2 3 ) ) ) ’ ( 1 ) )
5 ( append ( append ( append ’ ( ) ’ ( 4 ) ) ’ ( ( 2 3 ) ) ) ’ ( 1 ) )
.
ић
6 ( append ( append ’ ( 4 ) ’ ( ( 2 3 ) ) ) ’ ( 1 ) )
7 ( append ’ ( 4 ( 2 3 ) ) ’ ( 1 ) )
ов

а.
8 ’ (4 (2 3) 1)
ат

ан
Гњ

ж
Слика 4.40 Приказ рекурзивног извршавања функциjе дефинисане на сл. 4.38 кад
jоj се саопшти изабрани улазни аргумент.

др
ан

за
ил

Међутим, функциjа дата на сл. 4.38 не мења редослед елемената у


су

угнежђеним листама. У секвенци рекурзивних позива, сваки издвоjени


М

елемент коjи представља угнежђену листу додаjе се на краj текуће листе,


а
1.

ав

без промене редоследа садржаних елемената. Да бисмо имплементирали


02

функционалност обртања редоследа елемената у угнежђеним листама,


пр

додаћемо следећи израз за условно извршавање у дефинициjу функциjе:


–2

а
20

• ако се издвоjи угнежђена листа, прво се врши промена редоследа ње-


Св

них елемената — у засебном рекурзивном позиву функциjе — и тако


20

генерисана листа додаjе се на краj текуће листе.


а.
©

иj

Употпуњено рекурзивно правило гласи:


рз

ако (car l) ниjе листа ,



 (append f ((cdr l)) (list (car l))),
ве

f (l) = (append f ((cdr l)) (list f ((car l)))), ако jе (car l) листа ,
empty, ако jе l празна листа .
на


(4.24)
д
Ра

Рекурзивна функциja коjа имплементира правило (4.24) приказана jе


на сл. 4.41. Резултати позивања ове функциjе кад jоj се саопштe изабрани
улазни аргументи приказани су на сл. 4.42. Може се приметити да допу-
њена функциjа врши обртање редоследа елемената у произвољно дубоко
угнежђеним листама.
Секвенца рекурзивних позива извршених у поступку израчунавања
резултата приказана jе на сл. 4.43. У телу функциjе врше се два рекур-
122 4 Рекурзивне структуре података

зивна позива, па jе приказ поступка израчунавања заснован на претпо-


ставци да се делови израза коjи се налазе на истом хиjерархиjском нивоу
израчунаваjу у редоследу слева-надесно7 . Важно jе приметити да ова
претпоставка не утиче на краjњи резултат извршавања функциjе, и да jе
усвоjена с намером да се илуструjе редослед рекурзивних позива у овом
примеру, без губитка општости.

1 ( define ( o k r e n i l )
2 ( cond
3 [ ( empty? l ) empty ]
4 [ ( l i s t ? ( car l ) ) ( append ( o k r e n i ( cdr l ) )
5 ( l i s t ( o k r e n i ( car l ) ) ) ) ]
6 [ e l s e ( append ( o k r e n i ( cdr l ) ) ( l i s t ( car l ) ) ) ] ) )

.
ић
Слика 4.41 Рекурзивна функциjа коjа обрће редослед елемената у листи — и свим
ов
угнежђеним листама.

а.
ат

ан
Гњ

ж
 

др
> ( okreni ’ (1 2 3 4))
ан

’ (4 3 2 1)
за
> ( okreni ’ ())
ил

’ ()
су

> ( okreni ’ (1 (2 3) 4))


М

’ (4 (3 2) 1)
а

> ( okreni ’ (1 (2 (3 4) 5) 6))


1.

ав

’ (6 (5 (4 3) 2) 1)
02

 
пр
–2

Слика 4.42 Резултати позивања функциjе дефинисане на сл. 4.41 кад jоj се саопште
а
20

Св

изабрани улазни аргументи.


20

а.
©

(ii) Дефинисање итеративног процеса. Репно-рекурзивна функциjа


иj

коjа обрће редослед елемената у улазноj листи — и свим угнежђеним ли-


рз

стама — приказана jе на сл. 4.44. Слично као у примеру 4.15, указаћемо


на разлику између рекурзивног процеса дефинисаног на сл. 4.41, и итера-
ве

тивног процеса дефинисаног на сл. 4.44. Иако се у оба процеса елементи


на

улазне листе издваjаjу од првог елемента ка последњем, редоследи дода-


вања издвоjених елемената у текућу листу се разликуjу. У рекурзивном
д
Ра

процесу, сваки издвоjени елемент се, после евентуалне обраде, применом


функциjе append додаjе на краj текуће листе. За разлику од тога, у ите-
ративном процесу, сваки издвоjени елемент се, после евентуалне обраде,
применом функциjе cons додаjе на почетак помоћне листе.
Резултати позивања функциjе коjа имплементира итеративни процес
кад jоj се саопштe изабрани улазни аргументи jеднаки су резултатима по-
7
Иста претпоставка била jе усвоjена у примеру 3.7, у 3. поглављу.
4.4 Изабране основне функциjе над листама 123

1 ( okreni ’ (1 (2 3) 4))
2 ( append ( okreni ’ ((2 3) 4)) ’ ( 1 ) )
3 ( append ( append ( o k r e n i ’ ( 4 ) ) ( l i s t ( o k r e n i ’ ( 2 3 ) ) ) ) ’ ( 1 ) )
4 ( append ( append ( append ( o k r e n i ’ ( ) ) ’ ( 4 ) )
5 ( l i s t ( okreni ’ (2 3 ) ) ) ) ’ ( 1 ) )
6 ( append ( append ( append ’ ( ) ’ ( 4 ) )
7 ( l i s t ( okreni ’ (2 3 ) ) ) ) ’ ( 1 ) )
8 ( append ( append ’ ( 4 ) ( l i s t ( o k r e n i ’ ( 2 3 ) ) ) ) ’ ( 1 ) )
9 ( append ( append ’ ( 4 ) ( l i s t ( append ( o k r e n i ’ ( 3 ) ) ’ ( 2 ) ) ) ) ’ ( 1 ) )
10 ( append ( append ’ ( 4 ) ( l i s t ( append ( append
11 ( okreni ’ ()) ’ (3)) ’ (2)))) ’ (1))
12 ( append ( append ’ ( 4 ) ( l i s t ( append ( append
13 ’ () ’ (3)) ’ (2)))) ’ (1))
14 ( append ( append ’ ( 4 ) ( l i s t ( append ’ ( 3 ) ’ ( 2 ) ) ) ) ’ ( 1 ) )
15 ( append ( append ’ ( 4 ) ( l i s t ’ ( 3 2 ) ) ) ’ ( 1 ) )
16 ( append ( append ’ ( 4 ) ’ ( ( 3 2 ) ) ) ’ ( 1 ) )
.
ић
17 ( append ’ ( 4 ( 3 2 ) ) ’ ( 1 ) )
18 ’ (4 (3 2) 1)
ов

а.
ат

ан
Слика 4.43 Приказ рекурзивног извршавања функциjе дефинисане на сл. 4.41 кад
jоj се саопшти изабрани улазни аргумент.
Гњ

ж
др
ан

зивања претходно дефинисане функциjе коjа имплементира рекурзивни


за
ил

процес (в. сл. 4.42). Секвенца рекурзивних позива извршених у итера-


су

тивном процесу разликуjе се од претходног решења, и приказана jе на


М

сл. 4.45.
а
1.

ав
02

пр

1 ( define ( o k r e n i − r l [ a empty ] )
–2

2 ( cond
а

3 [ ( empty? l ) a ]
20

Св

4 [ ( l i s t ? ( car l ) )
5 ( o k r e n i − r ( cdr l ) ( cons ( o k r e n i − r ( car l ) ) a ) ) ]
20

6 [ e l s e ( o k r e n i − r ( cdr l ) ( cons ( car l ) a ) ) ] ) )


а.
©

иj
рз

Слика 4.44 Репно-рекурзивна функциjа коjа обрће редослед елемената у листи — и


свим угнежђеним листама.
ве
д на
Ра

4.4.7 Збир броjева у листи

Пример 4.20. Дефинишимо функциjу коjа прихвата листу, и израчунава


збир свих броjева садржаних у саопштеноj листи. Притом, улазна листа
може да садржи елементе произвољних типова података, укључуjући и
вишеструко угнежђене листе.
124 4 Рекурзивне структуре података

1 ( okreni−r ’ (1 (2 3) 4))
2 ( okreni−r ’ ((2 3) 4) ’ ( 1 ) )
3 ( okreni−r ’ ( 4 ) ( cons ( o k r e n i − r ’ ( 2 3 ) ) ’ ( 1 ) ) )
4 ( okreni−r ’ ( 4 ) ( cons ( o k r e n i − r ’ ( 3 ) ’ ( 2 ) ) ’ ( 1 ) ) )
5 ( okreni−r ’ ( 4 ) ( cons ( o k r e n i − r ’ ( ) ’ ( 3 2 ) ) ’ ( 1 ) ) )
6 ( okreni−r ’ ( 4 ) ( cons ’ ( 3 2 ) ’ ( 1 ) ) )
7 ( okreni−r ’ (4) ’ ((3 2) 1))
8 ( okreni−r ’ ( ) ’ (4 (3 2) 1))
9 ’ (4 (3 2) 1)

Слика 4.45 Приказ итеративног извршавања функциjе дефинисане на сл. 4.44 кад
jоj се саопшти изабрани улазни аргумент.

Правила за рекурзивни и итеративни процес израчунавања траженог


.
ић
резултата могу се извести комбиновањем правила датих у примерима:
ов

• израчунавања збира цифара датог ненегативног целог броjа (в. пример

а.
ат

3.1 у 3. поглављу),

ан
• обртања редоследа елемената у листи (в. пример 4.19 у овом погла-
Гњ

ж
вљу).

др
Због тога су у наставку представљена решења, без разматрања поступка
ан

за
њиховог извођења8 .
ил

Рекурзивни процес израчунавања збира броjева у листи може се пред-


су
М

ставити следећим правилом:


а
1.

ав

ако jе l празна листа ,



0,
02


ако jе e0 броj ,
пр

e0 + f (’ (e1 , ..., en−1 )),






–2


 | {z }
(cdr l)


а


e0 ) + f (’ (e1 , ..., en−1 )), ако jе e0 листа ,
20

f (’ (e0 , e1 , ..., en−1 )) = f ( |{z}


Св

| {z }  | {z }
20

(car l)
 (cdr l)
l 

у супротном .

f (’ (e1 , ..., en−1 )),
а.


©




иj

 | {z }
(cdr l)
(4.25)
рз
ве

Рекурзивна функциja коjа имплементира правило (4.25) приказана jе


на сл. 4.46. Резултати позивања ове функциjе кад jоj се саопштe изабра-
на

ни улазни аргументи приказани су на сл. 4.47, а секвенца рекурзивних


д

позива извршених у поступку израчунавања резултата на сл. 4.48.


Ра

Итеративни процес израчунавања збира броjева у листи може се пред-


ставити следећим правилом:

8
Читаоцу се оставља да интерпретира дата правила.
4.5 Изабране функциjе вишег реда над листама 125

1 ( define ( z b i r l )
2 ( cond
3 [ ( empty? l ) 0 ]
4 [ ( number? ( car l ) ) (+ ( car l ) ( z b i r ( cdr l ) ) ) ]
5 [ ( l i s t ? ( car l ) ) (+ ( z b i r ( car l ) ) ( z b i r ( cdr l ) ) ) ]
6 [ e l s e ( z b i r ( cdr l ) ) ] ) )

Слика 4.46 Рекурзивна функциjа коjа израчунава збир броjева садржаних у листи.
 
> ( zbir ’ ( " a " "b" " c " ) )
0
> ( zbir ’ (1 2 3 4))
10
> ( zbir ’ ( 1 " a " 2 #t 3 "b" 4 ) )
10
.
ић
> ( zbir ’ ( ( 1 ( " a " 2 ) #t ) 3 ( " b" 4 ) ) )
10
ов

 

а.
ат

ан
Слика 4.47 Резултати позивања функциjе дефинисане на сл. 4.46 кад jоj се саопште
Гњ

ж
изабрани улазни аргументи.

др
ан


a,
за l jе празна листа,
ил


f (’ (e1 , ..., en−1 ), a + e0 ), e0 jе броj ,

су



М


 | {z } |{z}

 (cdr l) (car l)
а


f (’ (e0 , e1 , ..., en−1 ), a) = f (’ (e 1 , ..., en−1 ), a + f ( e0 )), e0 jе листа ,
1.

ав

| {z }  | {z } |{z}
02

(car l)
 (cdr l)
l
пр



у супротном ,

 f (’ (e1 , ..., en−1 )),
–2




 | {z }
а

(cdr l)
20

Св

(4.26)
20

при чему jе вредност улазног аргумента a у инициjалном позиву функ-


а.

циjе jеднака 0.
©

иj

Репно-рекурзивна функциja коjа имплементира итеративни процес за-


снован на правилу (4.26) приказана jе на сл. 4.49. Резултати позивања ове
рз

функциjе кад jоj се саопштe изабрани улазни аргументи jеднаки су ре-


ве

зултатима позивања претходно дефинисане функциjе коjа имплементира


рекурзивни процес (в. сл. 4.47). Секвенца рекурзивних позива извршених
на

у итеративном процесу приказана jе на сл. 4.50.


д
Ра

4.5 Изабране функциjе вишег реда над листама

У овоj секциjи представљене су изабране функциjе вишег реда над


листама, унапред дефинисане у програмском jезику Ракет. Исто као у
126 4 Рекурзивне структуре података

1 ( z b i r ’ ( ( 1 (" a" 2 ) ) 3 ) )
2 (+ ( z b i r ’ ( 1 ( " a " 2 ) ) ) ( z b i r ’ ( 3 ) ) )
3 (+ (+ 1 ( z b i r ’ ( ( " a " 2 ) ) ) ) ( z b i r ’ ( 3 ) ) )
4 (+ (+ 1 (+ ( z b i r ’ ( " a " 2 ) ) ( z b i r ’ ( ) ) ) ) ( z b i r ’ ( 3 ) ) )
5 (+ (+ 1 (+ ( z b i r ’ ( 2 ) ) ( z b i r ’ ( ) ) ) ) ( z b i r ’ ( 3 ) ) )
6 (+ (+ 1 (+ (+ 2 ( z b i r ’ ( ) ) ) ( z b i r ’ ( ) ) ) ) ( z b i r ’ ( 3 ) ) )
7 (+ (+ 1 (+ (+ 2 0 ) ( z b i r ’ ( ) ) ) ) ( z b i r ’ ( 3 ) ) )
8 (+ (+ 1 (+ 2 ( z b i r ’ ( ) ) ) ) ( z b i r ’ ( 3 ) ) )
9 (+ (+ 1 (+ 2 0 ) ) ( z b i r ’ ( 3 ) ) )
10 (+ (+ 1 2 ) ( z b i r ’ ( 3 ) ) )
11 (+ 3 ( z b i r ’ ( 3 ) ) )
12 (+ 3 (+ 3 ( z b i r ’ ( ) ) ) )
13 (+ 3 (+ 3 0 ) )
14 (+ 3 3 )
15 6

.
ић
Слика 4.48 Приказ рекурзивног извршавања функциjе дефинисане на сл. 4.46 кад
ов
jоj се саопшти изабрани улазни аргумент.

а.
ат

ан
1 ( define ( z b i r − r l [ a 0 ] )
Гњ

ж
2 ( cond
3 [ ( empty? l ) a ]

др
4 [ ( number? ( car l ) ) ( z b i r − r ( cdr l ) (+ a ( car l ) ) ) ]
ан

5
за
[ ( l i s t ? ( car l ) ) ( z b i r − r ( cdr l ) (+ a ( z b i r − r ( car l ) ) ) ) ]
6 [ e l s e ( z b i r − r ( cdr l ) a ) ] ) )
ил

су
М

Слика 4.49 Репно-рекурзивна функциjа коjа израчунава збир броjева садржаних у


а
1.

листи.
ав
02

пр

1 ( zbir−r ’ ((1 (" a" 2)) 3))


–2

2 ( zbir−r ’ ( 3 ) (+ 0 ( zbir−r ’ (1 (" a" 2 ) ) ) ) )


а

3 ( zbir−r ’ ( 3 ) (+ 0 ( zbir−r ’ ( ( " a" 2 ) ) 1 ) ) )


20

Св

4 ( zbir−r ’ ( 3 ) (+ 0 ( zbir−r ’ ( ) (+ 1 ( z b i r − r ’ ( " a " 2 ) ) ) ) ) )


20

5 ( zbir−r ’ ( 3 ) (+ 0 ( zbir−r ’ ( ) (+ 1 ( z b i r − r ’ ( 2 ) 0 ) ) ) ) )
а.

6 ( zbir−r ’ ( 3 ) (+ 0 ( zbir−r ’ ( ) (+ 1 ( z b i r − r ’ ( ) 2 ) ) ) ) )
©

7 ( zbir−r ’ ( 3 ) (+ 0 ( zbir−r ’ ( ) (+ 1 2 ) ) ) )
иj

8 ( zbir−r ’ ( 3 ) (+ 0 ( zbir−r ’ () 3)))


рз

9 ( zbir−r ’ ( 3 ) (+ 0 3))
10 ( zbir−r ’ (3) 3)
ве

11 ( zbir−r ’ ( ) 6)
12 6
д на
Ра

Слика 4.50 Приказ итеративног извршавања функциjе дефинисане на сл. 4.49 кад
jоj се саопшти изабрани улазни аргумент.
4.5 Изабране функциjе вишег реда над листама 127

претходноj секциjи, већину представљених функциjа дефинисаћемо са-


мостално.

4.5.1 Пресликавање листи

Функциjа map прихвата следеће улазне аргументе:


• функциjу p коjа прихвата k улазних аргумената,
• k листи — l1 , l2 , . . . , lk — jеднаких дужина, од коjих свака садржи по n
елемената,
и генерише листу коjа такође садржи n елемената, при чему елемент на
i-том месту резултуjуће листе представља вредност добиjену позивањем
.
ић
функциjе p кад jоj се редом саопште елементи на i-тим местима у листама
l1 , l2 , . . . , lk .
ов

а.
Пример 4.21. Резултати позивања функциjе map кад jоj се саопште иза-
ат

ан
брани аргументи приказани су на сл. 4.51.
Гњ

ж
др
 
ан

> ( define l 1 ’ ( 1 2 3 4 ) ) за ← улазне листе


> ( define l 2 ’ ( 5 6 7 8 ) )
ил

су

> (map (lambda ( x ) (+ x 1 ) ) l 1 )


М

’ (2 3 4 5) ← елементи листе l1 увећани за 1


а
1.

ав

> (map + l 1 l 2 )
02

пр

’ ( 6 8 10 1 2 ) ← сабирање листи l1 и l2
–2

> (map + l 1 l 2 l 2 )
а
20

’ ( 1 1 14 17 2 0 ) ← сабирање листи l1 , l2 и l2
Св

 
20

а.
©

Слика 4.51 Резултати позивања функциjе map кад jоj се саопште изабрани аргу-
иj

менти.
рз
ве

Пример 4.22. Дефинишимо функциjу коjа прихвата функциjу p и листу


l = ’(e0 e1 . . . en−1 ), и генерише листу ’(( f e0 ) ( f e1 ) . . . ( f en−1 )).
на

Прво ћемо размотрити рекурзивни процес израчунавања траженог ре-


д

зултата. Ако jе улазна листа празна, функциjа треба да генерише празну


Ра

листу. У супротном, резултат позивања функциjе за непразну листу l


коjа садржи n елемената:

’(e0 , e1 , ..., en−1 ) , (4.27)

где jе n ≥ 1, може се представити на следећи начин9 :


9
Слично правило за рекурзивни процес изведено jе у примеру 4.15 у овом поглављу.
128 4 Рекурзивне структуре података

f (p, ’( e0 , e1 , ..., en−1 )) = (cons (p e0 ) f (p, ’(e1 , ..., en−1 ))) . (4.28)
| {z } | {z }
(cdr l ) (cdr l )

Рекурзивно правило и услов за излазак из секвенце рекурзивних по-


зива могу се представити обjедињено:

(cons (p (car l)) f (p,(cdr l))), ако l ниjе празна листа ,



f (p, l) =
empty, ако jе l празна листа .
(4.29)

Функциja коjа имплементира рекурзивни процес заснован на правилу


(4.29) приказана jе на сл. 4.52. Резултати позивања ове функциjе кад jоj се
саопштe изабрани улазни аргументи приказани су на сл. 4.53, а секвенца
рекурзивних позива извршених у поступку израчунавања резултата на
.
ић
сл. 4.54.
ов

а.
ат

1 ( define ( m a p i r a j f l )

ан
2 ( i f ( empty? l )
Гњ

ж
3 empty

др
4 ( cons ( f ( car l ) ) ( m a p i r a j f ( cdr l ) ) ) ) )
ан

за
ил

Слика 4.52 Рекурзивна функциjа коjа прихвата функциjу p и листу l =


су
’ (e0 e1 . . . en−1 ), и генерише листу ’ (( f e0 ) ( f e1 ) . . . ( f en−1 )).
М

а
1.

ав
02

 
пр

> ( m a p i r a j (lambda ( x ) (+ x 1 ) ) ’ ( 1 2 3 4 ) )
–2

’ (2 3 4 5)
а
20

> ( m a p i r a j number? ’ ( 1 " a " 2 ) )


Св

’ ( #t #f #t )
20

 
а.
©

иj

Слика 4.53 Резултати позивања функциjе дефинисане на сл. 4.52 кад jоj се саопште
изабрани улазни аргументи.
рз
ве

У итеративном процесу, сваки издвоjени елемент саопштава се функ-


на

циjи p, и тако генерисани резултат додаjе се на краj помоћнe листе a,


тj.10 :
д
Ра

f (p, ’ ( ei , ei+1 , ..., en−1 ), ’ ((p e0 ), (p e1 ), . . . , (p ei−1 )))


| {z } | {z }
листа l листа l1
(4.30)
= f (p, ’ (ei+1 , ..., en−1 ), ’ ((p e0 ), (p e1 ), . . . , (p ei−1 ), (p ei ) ))
| {z } | {z }
(cdr l) (append l1 (list (p (car l))))

10
Слично правило за итеративни процес изведено jе у примеру 4.15 у овом поглављу.
4.5 Изабране функциjе вишег реда над листама 129

1 ( m a p i r a j number? ’ ( 1 " a " 2 ) )


2 ( cons ( number? 1 ) ( m a p i r a j number? ’ ( " a " 2 ) ) )
3 ( cons #t ( m a p i r a j number? ’ ( " a " 2 ) ) )
4 ( cons #t ( cons ( number? " a " ) ( m a p i r a j number? ’ ( 2 ) ) ) )
5 ( cons #t ( cons #f ( m a p i r a j number? ’ ( 2 ) ) ) )
6 ( cons #t ( cons #f ( cons ( number? 2 ) ( m a p i r a j number? ’ ( ) ) ) ) )
7 ( cons #t ( cons #f ( cons #t ( m a p i r a j number? ’ ( ) ) ) ) )
8 ( cons #t ( cons #f ( cons #t empty ) ) )
9 ( cons #t ( cons #f ’ ( #t ) ) )
10 ( cons #t ’ ( #f #t ) )
11 ’ ( #t #f #t )

Слика 4.54 Приказ рекурзивног извршавања функциjе дефинисане на сл. 4.52 кад
jоj се саопште изабрани улазни аргументи.

.
ић
Кад се издвоjе сви елементи из улазне листе, извршавање функциjе се
ов

а.
завршава, а функциjа враћа помоћну листу a као резултат. Ово правило
ат

ан
може се формулисати:
Гњ

ж
f (p, (cdr l), (append a (list (p (car l))))), l ниjе празна листа ,


др
f (p, l, a) =
a, l jе празна листа ,
ан

(4.31)
за
ил

при чему jе вредност улазног аргумента a у инициjалном позиву функ-


су

циjе jеднака празноj листи.


М

Функциja коjа имплементира итеративни процес заснован на правилу


а

(4.31) приказана jе на сл. 4.55. Резултати позивања ове функциjе кад jоj
1.

ав

се саопштe изабрани улазни аргументи jеднаки су резултатима позивања


02

пр

претходно дефинисане функциjе коjа имплементира рекурзивни процес


–2

израчунавања (в. сл. 4.53), a секвенца рекурзивних позива извршених у


а
20

итеративном процесу приказана jе на сл. 4.56.


Св
20

а.
©

1 ( define ( mapiraj − r p l [ a empty ] )


иj

2 ( i f ( empty? l )
рз

3 a
4 ( mapiraj − r p ( cdr l ) ( append a ( l i s t ( p ( car l ) ) ) ) ) ) )
ве
на

Слика 4.55 Репно-рекурзивна функциjа коjа прихвата функциjу p и листу l =


’ (e0 e1 . . . en−1 ), и генерише листу ’ (( f e0 ) ( f e1 ) . . . ( f en−1 )).
д
Ра
130 4 Рекурзивне структуре података

1 ( mapiraj − r number? ’ (1 "a" 2 ) )


2 ( mapiraj − r number? ’ ( " a " 2 ) ( append empty ( l i s t ( number? 1 ) ) ) )
3 ( mapiraj − r number? ’ ( " a " 2 ) ( append empty ( l i s t #t ) ) )
4 ( mapiraj − r number? ’ ( " a " 2 ) ( append empty ’ ( #t ) ) )
5 ( mapiraj − r number? ’ ( " a " 2 ) ’ ( #t ) )
6 ( mapiraj − r number? ’ ( 2 ) ( append ’ ( #t ) ( l i s t ( number? " a " ) ) ) )
7 ( mapiraj − r number? ’ ( 2 ) ( append ’ ( #t ) ( l i s t #f ) ) )
8 ( mapiraj − r number? ’ ( 2 ) ( append ’ ( #t ) ’ ( #f ) ) )
9 ( mapiraj − r number? ’ ( 2 ) ’ ( #t #f ) )
10 ( mapiraj − r number? ’ ( ) ( append ’ ( #t #f ) ( l i s t ( number? 2 ) ) ) )
11 ( mapiraj − r number? ’ ( ) ( append ’ ( #t #f ) ( l i s t #t ) ) )
12 ( mapiraj − r number? ’ ( ) ( append ’ ( #t #f ) ’ ( #t ) ) )
13 ( mapiraj − r number? ’ ( ) ’ ( #t #f #t ) )
14 ’ ( #t #f #t )

.
Слика 4.56 Приказ итеративног извршавања функциjе дефинисане на сл. 4.55 кад
ић
jоj се саопште изабрани улазни аргументи.
ов

а.
ат

ан
4.5.2 Филтрирање листе
Гњ

ж
др
Функциjа filter прихвата функциjу p и листу l, и генерише листу коjа
ан

садржи оне елементе из листе l за коjе функциjа p генерише вредност


за
ил

#t, у редоследу у ком су наведени у улазноj листи.


су
М

Пример 4.23. Резултати позивања функциjе filter кад jоj се саопште иза-
а

брани аргументи приказани су на сл. 4.57.


1.

ав
02

пр

 
–2

> ( define l ’ ( 1 7 56 109 22 4 9 ) ) ← улазнa листа


а
20

Св

> ( f i l t e r (lambda ( x ) (> x 5 0 ) ) l )


20

’ (56 109) ← издвоjени су броjеви већи од 50


а.
©

> ( f i l t e r (lambda ( x ) (= ( r e m a i n d e r x 2 ) 1 ) ) l )
иj

’ ( 1 7 109 4 9 ) ← издвоjени су непарни броjеви


 
рз
ве

Слика 4.57 Резултати позивања функциjе filter кад jоj се саопште изабрани аргу-
менти.
д на
Ра

Пример 4.24. Дефинишимо функциjу коjа прихвата функциjу p и листу


l, и генерише листу коjа садржи оне елементе из листе l за коjе функциjа
p генерише вредност #t, у редоследу у ком су наведени у улазноj листи.
Решење овог проблема може се добити прилагођавањем дефинициjа
функциjа датих у примеру 4.22. Овде ћемо представити само11 функци-

11
В. задатак 4.4.
4.5 Изабране функциjе вишег реда над листама 131

jу коjа имплементира итеративни процес израчунавања тражених резул-


тата — в. сл. 4.58. Резултати позивања ове функциjе кад jоj се саопштe
изабрани улазни аргументи приказани су на сл. 4.59.

1 ( define ( f i l t r i r a j p l [ a empty ] )
2 ( cond
3 [ ( empty? l ) a ]
4 [ ( p ( car l ) ) ( f i l t r i r a j p ( cdr l )
5 ( append a ( l i s t ( car l ) ) ) ) ]
6 [ e l s e ( f i l t r i r a j p ( cdr l ) a ) ] ) )

Слика 4.58 Функциjа коjа прихвата функциjу p и листу l , и генерише листу коjа
садржи оне елементе из листе l за коjе функциjа p генерише вредност #t, у редоследу
у ком су наведени у улазноj листи.
.
ић
ов

а.
ат

 

ан
> ( define l ’ ( 1 7 56 109 22 4 9 ) ) ← улазнa листа
Гњ

ж
др
> ( f i l t r i r a j (lambda ( x ) (> x 5 0 ) ) l )
’ (56 109) ← издвоjени су броjеви већи од 50
ан

за
ил

> ( f i l t r i r a j (lambda ( x ) (= ( r e m a i n d e r x 2 ) 1 ) ) l )
су

’ ( 1 7 109 4 9 ) ← издвоjени су непарни броjеви


М

 
а
1.

ав

Слика 4.59 Резултати позивања функциjе дефинисане на сл. 4.58 кад jоj се саопште
02

изабрани улазни аргументи.


пр
–2

а
20

Св
20

а.
©

4.5.3 Уређивање листе по задатом критериjуму


иj
рз

Функциjа sort уређуjе листу по задатом критериjуму. Ова функциjа


ве

прихвата четири улазна аргумента, од коjих су два обавезна:


• листa l,
на

• функциja p, коjа прихвата два елемента ei и e j листе l, и генерише


д

вредност #t ако ei треба да се налази пре e j у уређеноj листи, односно


Ра

#f, у супротном.
Да би се листа l уредила, функциjа p се примењуjе на сваку вариjациjу
два елемента ei и e j . Друга два улазна аргумента су именовани аргументи
с подразумеваним вредностима12 :
12
Именовани аргументи с подразумеваним вредностима обjашњени су у 2. поглављу,
в. секциjу 2.6.
132 4 Рекурзивне структуре података

• функциjа #:key прихвата елемент ei , и генерише вредност коjа предста-


вља елемент ei приликом поређења с другим елементима улазне листе,
тj., поступак поређења два елемента ei и e j формално се представља
следећим изразом:

(lambda (ei e j ) (p (#:key ei ) (#:key e j ))) , (4.32)

• буловска вредност #:cache − keys? омогућава оптимизовање извршава-


ња функциjе sort на следећи начин:
– ако jе вредност овог аргумента jеднака #f, функциjа #:key се позива
за сваку поjединачну вариjациjу два елемента листе l,
– у супротном, функциjа #:key се позива само jедном за сваки поjе-
диначни елемент листе — при чему се вредност коjу функциjа #:key
генерише за неки елемент листе чува, и примењуjе у вариjациjама
.
ић
коjе садрже дати елемент.
ов

а.
Именованим аргументима #:keys и #:cache − keys? додељене су респек-
ат

ан
тивно следеће подразумеване вредности: (lambda (x) x) и #f.
Гњ

ж
Пример 4.25. Резултати позивања функциjе sort кад jоj се саопште иза-

др
брани аргументи приказани су на сл. 4.60. Треба приметити да функциjа
ан

p може да буде дефинисана тако да не даjе jеднозначну информациjу о


за
редоследу датих елемената ei и e j у уређеноj листи. Разликуjемо два
ил

случаjа:
су
М

• ако важи:
а
1.

ав

(= (p (#:key ei ) (#:key e j )) (p (#:key e j ) (#:key ei )) #f) , (4.33)


02

пр
–2

редослед елемената ei и e j у резултуjућоj листи исти jе као у улазноj


а

листи,
20

Св

• ако важи:
20

а.
©

(= (p (#:key ei ) (#:key e j )) (p (#:key e j ) (#:key ei )) #t) , (4.34)


иj
рз

редослед елемената ei и e j у резултуjућоj листи ниjе обавезно исти као


у улазноj листи.
ве

Нпр., три позива функциjе sort на сл. 4.60 уређуjу дату улазну листу тако
на

да цифре jединица броjева у уређеноj листи чине монотоно неопадаjући


д

низ. У два позива примењен jе оператор < као критериjум за поређе-


Ра

ње цифри jединица, и тада jе резултуjући редослед елемената 109 и 49,


коjи имаjу исту цифру jединица, исти као у улазноj листи. У трећем по-
зиву примењен jе оператор <=, и тада редослед елемената 109 и 49 у
резултуjућоj листи ниjе исти као у улазноj.
Пример 4.26. Дефинишимо функциjу коjа прихвата листу l и функци-
jу p, и генерише нову листу коjа садржи елементе листе l уређене по
критериjуму коjи спецификуjе функциjа p.
4.5 Изабране функциjе вишег реда над листама 133
 
> ( define l ’ ( 4 9 56 109 17 2 2 ) ) ← улазнa листа

> ( sort l <)


’ ( 1 7 22 49 56 1 0 9 ) ← броjеви уређени монотоно неопадаjуће

> ( sort l < #: key (lambda ( x ) ( r e m a i n d e r x 1 0 ) ) )


’ ( 2 2 56 17 49 1 0 9 ) ← цифре jединица уређене монотоно неопадаjуће,
при чему jе редослед „ jеднаких” елемената исти као у улазноj листи

> ( sort l (lambda ( x y )


(< ( r e m a i n d e r x 1 0 ) ( r e m a i n d e r y 1 0 ) ) ) )
’ ( 2 2 56 17 49 1 0 9 ) ← цифре jединица уређене монотоно неопадаjуће,
при чему jе редослед „ jеднаких” елемената исти као у улазноj листи

> ( sort l (lambda ( x y )


(<= ( r e m a i n d e r x 1 0 ) ( r e m a i n d e r y 1 0 ) ) ) )
.
ић
’ ( 2 2 56 17 109 4 9 ) ← цифре jединица уређене монотоно неопадаjуће,
при чему редослед „ jеднаких” елемената ниjе исти као у улазноj листи
ов

а.
> ( sort l (lambda ( x y )
ат

ан
( and (= ( r e m a i n d e r x 2 ) 0 )
Гњ

(= ( r e m a i n d e r y 2 ) 1 ) ) ) )

ж
’ ( 5 6 22 49 109 1 7 ) ← парни броjеви претходе непарним, при чему jе

др
редослед парних броjева исти као у улазноj листи
ан

за
> ( sort l (lambda ( x y )
ил

(= ( r e m a i n d e r x 2 ) 0 ) ) )
су
М

’ ( 2 2 56 49 109 1 7 ) ← парни броjеви претходе непарним, при чему


редослед парних броjева ниjе исти као у улазноj листи
а

 
1.

ав
02

пр

Слика 4.60 Резултати позивања функциjе sort кад jоj се саопште изабрани аргумен-
–2

ти.
а
20

Св
20

Оваj проблем ћемо решити применом тзв. алгоритма за брзо уређење,


а.

коjи се може представити следећим рекурзивним правилом. Ако jе листа


©

иj

l празна, функциjа f генерише празну листу. У супротном, изабере се


рз

jедан елемент c из листе l, а сви преостали елементи се расподеле на две


листе, l1 и l2 , при чему:
ве

• листа l1 садржи све елементе e улазне листе l коjи су „мањи” од еле-


на

мента c, тj., за коjе важи:


д
Ра

(= (p e c) #t) , (4.35)

• листа l2 садржи све елементе e улазне листе l коjи нису „мањи” од


елемента c, тj., за коjе важи:

(= (p e c) #f) . (4.36)
134 4 Рекурзивне структуре података

Листе l1 и l2 понаособ се уређуjу рекурзивним позивањем описаноg ал-


горитма, а резултуjућа листа се добиjа спаjањем уређене листе l1 , листе
коjа садржи елемент c, и уређене листе l2 , тj.:

f (l, p) = (append f (l1 , p) (list c) f (l2 , p)) . (4.37)

Рекурзивна функциjа коjа имплементира оваj алгоритам приказана jе


на сл. 4.61. Елемент c, коjи се, у општем случаjу, може изабрати као
произвољни елемент непразне листе l, у овом решењу дефинише се, без
губитка општости, као први елемент листе l. Резултати позивања ове
функциjе кад jоj се саопштe изабрани улазни аргументи приказани су на
сл. 4.62, а поступак извршавања илустрован jе на сл. 4.63.

1 ( define ( u r e d i l p )
.
ић
2 ( cond
ов
3 [ ( empty? l ) empty ]

а.
4 [ else ( let ∗
ат

ан
5 ( [ c ( car l ) ]
Гњ

6 [ l 1 ( f i l t e r (lambda ( e ) ( p e c ) ) ( cdr l ) ) ]

ж
7 [ l 2 ( f i l t e r (lambda ( e ) ( not ( p e c ) ) ) ( cdr l ) ) ] )

др
8 ( append ( u r e d i l 1 p )
ан

9 ( list c) за
10 ( uredi l2 p ) ) ) ] ) )
ил

су
М

Слика 4.61 Функциjа коjа прихвата листу l и функциjу p, и генерише нову листу
а

коjа садржи елементе листе l уређене по критериjуму коjи спецификуjе функциjа p.


1.

ав
02

пр
–2

а
20

Св
20

4.6 Функциjе с произвољним броjем улазних


а.

аргумената
©

иj
рз

У 2. поглављу (в. секциjу 2.4) представљена jе следећа синтаксичка


структура дефинициjе безимене функциjе:
ве
на

(lambda (niz−ulaznih−argumenata) izraz) . (4.38)


д

Први елемент ове синтаксичке структуре чини симбол lambda, други еле-
Ра

мент jе низ улазних аргумената наведених у заградама, а трећи елемент


чини подизраз коjи израчунава вредност безимене функциjе. Овде ћемо
посматрати специjални случаj синтаксичке структуре дефинициjе бези-
мене функциjе:
(lambda ulazni−argument izraz) . (4.39)
4.6 Функциjе с произвољним броjем улазних аргумената 135
 
( define l ’ ( 4 9 56 109 17 2 2 ) )

> ( u r e d i l <)
’ ( 1 7 22 49 56 1 0 9 )

> ( u r e d i l (lambda ( x y )
(< ( r e m a i n d e r x 1 0 ) ( r e m a i n d e r y 1 0 ) ) ) )
’ ( 2 2 56 17 49 1 0 9 )

> ( u r e d i l (lambda ( x y )
(<= ( r e m a i n d e r x 1 0 ) ( r e m a i n d e r y 1 0 ) ) ) )
’ ( 2 2 56 17 109 4 9 )

> ( u r e d i l (lambda ( x y )
( and (= ( r e m a i n d e r x 2 ) 0 )
(= ( r e m a i n d e r y 2 ) 1 ) ) ) )
.
ић
’ ( 5 6 22 49 109 1 7 )
ов

> ( u r e d i l (lambda ( x y )

а.
(= ( r e m a i n d e r x 2 ) 0 ) ) )
ат

ан
’ ( 2 2 56 49 109 1 7 )
 
Гњ

ж
др
Слика 4.62 Резултати позивања функциjе дефинисане на сл. 4.61 кад jоj се саопште
ан

изабрани улазни аргументи.


за
ил

су
’ ( 22 19 109 56 47 1 7 )
М

’ ( 19 17) ’ ( 22 ) ’ ( 109 56 4 7 )
1.

ав
02

’ ( 17 ) ’ ( 19 ) ’ ( ) ’ ( 56 47) ’ ( 109 ) ’ ()
пр
–2

’ ( 47 ) ’ ( 56 ) ’ ( )
а
20

Св
20

’ ( 17 19 22 47 56 109 )
а.
©

иj
рз

Слика 4.63 Илустрациjа извршавања функциjе дефинисане на сл. 4.61, за позив:


(uredi ’(22 19 109 56 47 17) <).
ве
на

Разлика ове синтаксичке структуре у односу на структуру (4.38) jе та


д

што њен други елемент чини само jедан улазни аргумент, коjи ниjе на-
Ра

веден у заградама. Међутим, резултуjућа безимена функциjа прихвата


произвољни броj улазних аргумената, смештених у листу на коjу рефе-
рише други елемент синтаксичке структуре (4.39).

Пример 4.27. Дефинишимо функциjу коjа прихвата произвољно дугачку


секвенцу аргумената произвољних типова података, и израчунава збир
свих броjева садржаних у њоj.
136 4 Рекурзивне структуре података

Функциjа коjа представља решење овог проблема дата jе на сл. 4.64,


при чему се у њеном телу позива функциjа zbir, претходно дефинисана
у примеру 4.20 (в. сл. 4.46 и 4.49). Резултати позивања приказане функ-
циjе кад jоj се саопштe изабрани улазни аргументи приказани су на сл.
4.65. Треба приметити да се функциjа може позивати и без саопштавања
улазних аргумената, и у том случаjу генерише се вредност 0.

1 ( define s a b e r i
2 (lambda l ( z b i r l ) ) )

Слика 4.64 Функциjа коjа прихвата произвољно дугачку секвенцу аргумената про-
извољних типова података, и израчунава збир свих броjева садржаних у њоj.

.
ић
ов

 

а.
ат

> ( s a b e r i 1 2 3 4)

ан
10
Гњ

ж
> ( s a b e r i 1 2 3 4 5 6)
21

др
> ( s a b e r i 1 " a " 2 #t 3 "b" 4 )
ан

10
за
ил

> ( s a b e r i " a " "b" " c " )


су
0
М

> ( s a b e r i ’ ( 1 ( " a " 2 ) #t ) 3 ’ ( " b" 4 ) )


а

10
1.

ав

> ( saberi ) ← функциjа се може позивати без саопштавања аргумената


02

0
пр

 
–2

Слика 4.65 Резултати позивања функциjе дефинисане на сл. 4.64 кад jоj се саопште
20

Св

изабрани улазни аргументи.


20

а.
©

иj

Ако желимо да искључимо могућност да резултуjућа функциjа може


рз

да се позива без саопштавања аргумената, улазни аргумент у синтаксич-


ве

коj структури (4.39) можемо да дефинишемо као уређени пар.


на

Пример 4.28. Дефинишимо функциjу коjа прихвата произвољно дугачку,


али непразну секвенцу броjева, и израчунава њихов максимум.
д
Ра

Решење овог проблема приказано jе на сл. 4.66, при чему се у телу


„главне” функциjе позива „помоћна” функциjа коjа израчунава макси-
мум дате листе броjева. Резултати позивања „главне” функциjе кад jоj
се саопштe изабрани улазни аргументи приказани су на сл. 4.67. Треба
приметити да иако се „помоћноj” функциjи може саопштити празна ли-
ста, „главна” функциjа не може се позивати без саопштавања улазних
аргумената.
4.7 Закључне напомене 137

1 ( define ( m a k s − l i s t e l [ a 0 ] ) ← „помоћна” функциjа


2 ( cond
3 [ ( empty? l ) a ]
4 [ e l s e ( m a k s − l i s t e ( cdr l ) ( i f (> a ( car l ) ) a ( car l ) ) ) ] ) )
5
6 ( define maksimum ← „главна” функциjа
7 (lambda ( p r v i . o s t a l i )
8 ( m a k s − l i s t e ( cons p r v i o s t a l i ) ) ) )

Слика 4.66 Функциjа коjа прихвата произвољни низ броjева, и израчунава њихов
збир.
 
> ( maksimum 1 5 7 3 )
7
> ( maksimum 1 5 7 3 12 0 )
.
ић
12
> ( maksimum 1 234 +i n f . 0 1 0 2 4 )
ов

а.
+i n f . 0
ат

> ( maksimum ) ← функциjа се не може позивати без саопштавања аргумената

ан
. . . maksimum : a r i t y mismatch ;
Гњ

ж
t h e e x p e c t e d number o f arguments d o e s not match
t h e g i v e n number

др
expected : at l e a s t 1
ан

given : 0
за
 
ил

су
М

Слика 4.67 Резултати позивања функциjе дефинисане на сл. 4.66 кад jоj се саопште
а

изабрани улазни аргументи.


1.

ав
02

пр

4.7 Закључне напомене


–2

а
20

Св

У овом поглављу представљене су листе, рекурзивнe структуре пода-


20

така коjе заузимаjу централно13 место у функционалном програмирању.


а.
©

Оно што чини листе корисним jе висок степен њихове експресивности.


иj

Листама се могу представљати други сложени типови података, попут


рз

матрица, графова, скупова, итд. Чак су и функциjе у програмском jе-


ве

зику Лисп изворно биле интерно представљане као листе, и jедино што
jе разликовало функциjе од „стандардних” листи било jе то што jе први
на

елемент функциjа био симбол lambda. Касниjе су функциjе почеле да се


интерно представљаjу другачиjе од листи, чиме jе симбол lambda постао
д
Ра

сувишан, али jе — због свог традиционалног значења у функционалном


програмирању — задржан у синтакси програмског jезика Лисп. На син-
таксичком нивоу, функциjе се и даље могу представљати као листе.

13
Важност листи у функционалном програмирању рефлектуjе се и кроз чињеницу да
име програмског jезика Лисп представља композитну реч насталу сажимањем фразе
„List Processor”.
138 4 Рекурзивне структуре података

Библиографскe напоменe:
• Интерно мемориjско представљање уређених парова и листи раз-
мотрено jе у поглављу „2 Lists” библиографског навода [31].
• Опсежниjи списак унапред дефинисаних функциjа над листама у
програмском jезику Ракет дат jе у секциjи „4.10 Pairs and Lists”
библиографског навода [6].
• Дефинисање функциjа за обраду листи размотрено jе у секциjи
„2.3 Lists, Iteration, and Recursion” библиографског навода [6].
• Алгоритам за брзо уређење секвенци описан jе у библиографском
наводу [13].
• Имплементациjа упрошћене верзиjе алгоритма за брзо уређивање
листе — коjа претпоставља да улазна листа садржи само разли-
.
ић
чите броjеве, и уређуjе листу растуће — дата jе у секциjи „25.2
Recursion that Ignores Structure” библиографског навода [5].
ов

а.
• Примена симбола lambda за дефинисање функциjа коjе при-
ат

ан
хватаjу произвољни броj аргумената описана jе у секциjи „4.4.1
Declaring a Rest Argument” библиографског навода [6].
Гњ

ж
• Етимолошко порекло композитних речи „Lisp”, „car” и „cdr” обjа-

др
шњено jе у секциjи „2.10 Car and Cdr” библиографског навода [31],
ан

за
и секциjи „LISP prehistory — Summer 1956 through Summer 1958”
ил

библиографског навода [20].


су

• Традиционални значаj симбола lambda описан jе у поглављу „2


М

Welcome to Lisp” библиографског навода [10].


а
1.

ав
02

пр
–2

а
20

Св

4.8 Задаци
20

а.
©

Напомена: Сви задаци, осим задатка 4.7, спецификовани су под прет-


иj

поставком да улазна листа може да садржи елементе произвољних ти-


рз

пова података, укључуjући и вишеструко угнежђене листе. (Савет: в.


ве

пример 4.20.)
на

Задатак 4.1. Дефинишите функциjу коjа прихвата листу l и ненегатив-


ни цели броj n, и враћа елемент листе l коjем jе додељен индекс n.
д
Ра

Задатак 4.2. Дефинишите функциjу коjа прихвата листу, и израчунава


збир свих позитивних броjева садржаних у саопштеноj листи.

Задатак 4.3. Дефинишите функциjу коjа прихвата листу, и израчунава:


• максимални броj коjи саопштена листа садржи,
• колико пута се максимални броj jавља у саопштеноj листи.
4.8 Задаци 139

Задатак 4.4. Дефинишите функциjу коjа имплементира рекурзивни про-


цес израчунавања резултата спецификованих у примеру 4.24.

Задатак 4.5. Дефинишите функциjу коjа прихвата листу l и функциjу


p, и:
а) генерише вредност #t, ако у листи l постоjи бар jедан елемент за коjи
функциjа p враћа вредност #t — односно вредност #f, у супротном,
б) израчунава броj елемената у листи l за коjе функциjа p враћа вредност
#t.

Задатак 4.6. Дефинишите функциjу коjа прихвата две листе, и утврђуjе


да ли су jеднаке.

Задатак 4.7. Дефинишите функциjу коjа прихвата листу чиjи су еле-


.
ић
менти само броjеви и стрингови, и уређуjе jе тако да су испуњени следећи
услови:
ов

а.
• броjеви претходе стринговима,
ат

ан
• броjеви су уређени монотоно неопадаjуће,
Гњ

ж
• стрингови су лексикографски уређени монотоно неопадаjуће.

др
ан

за
ил

су
М

а
1.

ав
02

пр
–2

а
20

Св
20

а.
©

иj
рз
ве
д на
Ра
©
20
20
–2
02
Ра 1.
д М
на ил
ве ан
рз Гњ
иj ат
а.
Св ов
а ић
.
пр
ав
а
су
за
др
ж
ан
а.
©
20
20
–2
02
Ра 1.
д М
на ил
ве ан
рз Гњ
иj ат
а.
Св ов
а ић
.
пр
ав
а
су
за
др
ж
ан
а.
програмирања
Концепти императивног
Део II
©
20
20
–2
02
Ра 1.
д М
на ил
ве ан
рз Гњ
иj ат
а.
Св ов
а ић
.
пр
ав
а
су
за
др
ж
ан
а.
Поглавље 5
Типови података и инструменти
апстракциjе у императивноj
парадигми

.
ић
5.1 Увод
ов

а.
ат

ан
У овом поглављу размотрени су атомски типови података и изабрани
инструменти апстракциjе у програмском jезику Ц, укључуjући: промен-
Гњ

ж
љиве, функциjе, условно извршавање, низове и показиваче. Иако jе ве-

др
ћина ових концепата већ обрађена у контексту функционалне парадигме
ан

за
програмирања, фокус разматрања у овом поглављу стављен jе на оне
ил

аспекте коjи су специфични за императивну парагидму програмирања и


су

програмски jезик Ц.
М

Намена овог поглавља jе да истакне jедну од фундаменталних разлика


а
1.

ав

између функционалног и императивног програмирања. У функционал-


02

ном програмирању, изрази су референтно транспарентни, што значи да


пр

се сваки израз може заменити своjом вредношћу, тj., вредност израза


–2

jе увек иста, без обзира на контекст у коjем се израчунава. Референт-


а
20

Св

на транспарентност израза у значаjноj мери олакшава интерпретирање


20

програма, jер смањуjе међусобну зависност различитих делова програ-


а.

ма. Jедан од потребних услова за референтну транспарентност jе таj да


©

иj

вредност израза представља jедини ефекат израчунавања израза, тj., да


не постоjе тзв. бочни ефекти коjи мењаjу „стање” програма независно од
рз

резултата израчунавања израза. У складу с тим, све функциjе у првом


ве

делу књиге дефинисане су математички, без бочних ефеката, а све про-


менљиве посматране су као константе1 — вредност инициjално додељена
на

променљивоj ниjе накнадно мењана.


д

У императивном програмирању, бочни ефекти представљаjу примарни


Ра

инструмент програмирања. Стање програма моделуjе се скупом промен-


љивих, чиjе се вредности мењаjу бочним ефектима извршавања наредби,
узрокуjући прелазак програма из тренутног стања у наредно стање. Због
бочних ефеката коjе изазиваjу, наредбе императивног програмирања ни-
су референтно транспарентне. С jедне стране, то повећава међусобну за-
1
В. секциjу 2.1 у 2. поглављу.

143
144 5 Типови података и инструменти апстракциjе у императивноj парадигми

висност различитих делова програмског ко̂да, и отежава интерпретирање


програма, док, с друге стране, омогућава ефикасниjи приступ мемориj-
ским садржаjима — што ће бити илустровано низом примера у овом и
наредном поглављу.

5.2 Атомски типови података

Скуп атомских типова података у програмском jезику Ц укључуjе:


• целе броjеве (int),
• реалне броjеве двоструке тачности (double),
• реалне броjеве jедноструке тачности (float),
• симболе (char). .
ић
Примери константи ових атомских типова података дати су у табели 5.1.
ов

а.
ат

ан
Гњ

Табела 5.1 Примери константи атомских типова података у програмском jезику Ц.

ж
др
Атомски тип података Примери константи
ан

цели броjеви: (int) 0, 1, −2


за
ил

реални броjеви двоструке тачности (double): 123.4, 1.234e2, −9.81


су

реални броjеви jедноструке тачности (float): 123.4f, 1.234e2f, −9.81f


М

симболи (char): ’a’, ’A’, ’b’, ’0’, ’1’, ’\n’


а
1.

ав
02

пр

Наведени скуп атомских типова података сличан jе скупу атомских


–2

типова података у програмском jезику Ракет, представљеном у 1. погла-


а
20

Св

вљу, па ћемо овде указати само на аспекте специфичне за програмски


20

jезик Ц:
а.
©

• За представљање реалних броjева користе се два атомска типа по-


иj

датака — броjеви у покретном зарезу jедноструке (float) и двоструке


рз

(double) тачности. У општем случаjу, ова два типа података разликуjу


ве

се по броjевима битова коjи се користе за представљање реалних броjе-


ва. Конкретне величине мемориjских репрезентациjа реалних броjева
на

зависе од партикуларне имплементациjе преводиоца, уз захтев да броj


битова коjи се користе за представљање вредности типа double ниjе
д
Ра

мањи од броjа битова коjе се користе за представљање вредности типа


float, чиме се постиже да прецизност записа реaлних вредности типа
double буде већа од или jеднака прецизности записа реaлних вредно-
сти типа float. Разлика између ова два типа неће бити од значаjа за
дискусиjу коjа следи у овоj књизи.
• Не постоjи атомски тип коjи представља комплексне броjеве.
5.2 Атомски типови података 145

• Симболичке константе су, у ствари, цели броjеви, тj., свака симболичка


константа представљена jе целоброjним машинским ко̂дом. То значи
да се над симболичким константама могу примењивати исте операциjе
као и над целим броjевима.
• Низови симбола и стрингови2 представљаjу сложене типове података.
• Не постоjи засебни атомски тип коjи представља буловске вредности.
Уместо тога, вредност нула представља буловску вредност нетачно, а
свака ненулта вредност представља буловску вредност тачно.

5.2.1 Основне операциjе над константама

У програмском jезику Ц, изрази се наводе у инфиксноj нотациjи, а


.
ић
сваки израз завршен тачком и зарезом (;) представља наредбу.
Оператори коjи извршаваjу основне операциjе над константама прика-
ов

а.
зани су у табели 5.2. Сви наведени оператори су бинарни, тj., примењуjу
ат

ан
се над два операнда, осим оператора негациjе (!), коjи jе унаран, тj., при-
Гњ

ж
мењуjе се над jедним операндом.

др
ан

за
Табела 5.2 Оператори коjи извршаваjу основне операциjе над константама у про-
ил

грамском jезику Ц. Сви наведени оператори су бинарни, осим оператора негациjе (!),
су

коjи jе унаран.
М

Категориjа Оператори
1.

ав

оператора
02

пр

аритметички: сабирање (+), одузимање (−), множење (∗), дељење (/),


–2

остатак при целоброjном дељењу (%)


а
20

релациони: jеднако (==), различито (! =), мање (<), мање или jеднако
Св

(<=), веће (>), веће или jеднако (>=)


20

буловски: конjункциja (&&), дисjункциja (||), негациja (!)


а.
©

иj
рз

Резултати примене аритметичких оператора сабирања (+), одузима-


ве

ња (−), множења (∗) и дељења (/) зависе од врсте броjева над коjима
су оператори примењени. Нпр., резултат сабирања целих броjева такође
на

jе цели броj. Ако jе бар jедан сабирак реални броj, тада jе и резултат
д

сабирања реални броj.


Ра

Пример 5.1. Зависност резултата примене оператора сабирања од врсте


броjева над коjима jе оператор примењен илустрована jе на сл. 5.1.

2
Разлика између низова симбола и стрингова обjашњена jе у секциjи 5.5.1 и илустро-
вана у примеру 5.26.
146 5 Типови података и инструменти апстракциjе у императивноj парадигми

1 1 + 2; ← израчуната вредност jеднака jе целом броjу 3


2 1.0 + 2; ← израчуната вредност jеднака jе реалном броjу 3,0
3 1.0 + 2. 0; ← израчуната вредност jеднака jе реалном броjу 3,0

Слика 5.1 Илустрациjа зависности резултата примене оператора сабирања од врсте


броjева над коjима jе оператор примењен.

Аналогне напомене важе и за друге аритметичке операторе. Међутим,


ова контекстуална зависност резултата примене аритметичких оператора
захтева посебну пажњу код операциjе дељења. Ако се операциjа дељења
изводи над два цела броjа, при чему вредност делиоца ниjе jеднака нули,
резултат jе цели броj коjи се добиjе тако што се у реалном количнику
занемари део коjи се налази после децималног сепаратора.
.
ић
Пример 5.2. Зависност резултата примене оператора дељења од врсте
ов

броjева над коjима jе оператор примењен илустрована jе на сл. 5.2.

а.
ат

ан
Гњ

ж
1 1 / 2; ← израчуната вредност jеднака jе целом броjу 0

др
2 99 / 1 0 0 ; ← израчуната вредност jеднака jе целом броjу 0
3 1.0 / 2; ← израчуната вредност jеднака jе реалном броjу 0,5
ан

4 99.0 / 100;
за
← израчуната вредност jеднака jе реалном броjу 0,99
ил

су
М

Слика 5.2 Илустрациjа зависности резултата примене оператора дељења од врсте


а

броjева над коjима jе оператор примењен.


1.

ав
02

пр
–2

Изузетак од горњег правила jе оператор %, коjи се примењуjе искљу-


а

чиво над два цела броjа, и враћа остатак целоброjног дељења првог броjа
20

Св

другим.
20

Пример 5.3. Jедна од примена оператора / и % односи се на издваjање


а.
©

цифара из целих броjева. Уклањање последње цифре из датог целог броjа


иj

врши се његовим целоброjним дељењем броjем 10, док се последња цифра


рз

датог целог броjа добиjа као остатак његовог целоброjног дељења броjем
ве

10. Ово jе илустровано на сл. 5.3.


д на

1 12345 / 1 0 ; ← израчуната вредност jеднака jе целом броjу 1234


Ра

2 12345 % 1 0 ; ← израчуната вредност jеднака jе целом броjу 5

Слика 5.3 Илустрациjа издваjања цифара из целог броjа у програмском jезику Ц.

Релациони оператори се примењуjу над два броjа, а њихово изврша-


вање генерише следеће резултате:
5.2 Атомски типови података 147

• оператор == генерише буловску вредност тачно (тj., вредност 1) ако су


вредности броjева над коjима jе оператор примењен jеднаке, односно
буловску вредност нетачно (тj., вредност 0), у супротном,
• оператор ! = генерише комплементарну буловску вредност у односу на
оператор ==, тj., генерише буловску вредност тачно ако су вредности
броjева над коjима jе оператор примењен различите, односно буловску
вредност нетачно, у супротном,
• оператор < генерише буловску вредност тачно ако jе вредност првог
броjа мања од вредности другог броjа, односно буловску вредност не-
тачно, у супротном,
• оператор <= генерише буловску вредност тачно ако jе вредност првог
броjа мања од или jеднака вредности другог броjа, односно буловску
вредност нетачно, у супротном,
• оператор > генерише буловску вредност тачно ако jе вредност првог
.
ић
броjа већа од вредности другог броjа, односно буловску вредност не-
тачно, у супротном,
ов

а.
• оператор >= генерише буловску вредност тачно ако jе вредност првог
ат

ан
броjа већа од или jеднака вредности другог броjа, односно буловску
Гњ

ж
вредност нетачно, у супротном.

др
Пример 5.4. Примена релационих оператора илустрована jе на сл. 5.4.
ан

за
ил

су

1 1 == 1 ; ← наредба генерише буловску вредност тачно


М

2 1 == 1 . 0 ; ← наредба генерише буловску вредност тачно


а

3 1 != 2 ; ← наредба генерише буловску вредност тачно


1.

ав

4 2 < 2; ← наредба генерише буловску вредност нетачно


02

пр

5 2 <= 2 . 0 ; ← наредба генерише буловску вредност тачно


6 2 > 2.1; ← наредба генерише буловску вредност нетачно
–2

7 1 >= 0 . 9 ; ← наредба генерише буловску вредност тачно


а
20

Св
20

Слика 5.4 Илустрациjа примене релационих оператора у програмском jезику Ц.


а.
©

иj
рз

Буловски оператори извршаваjу буловске функциjе конjункциjе (&&),


ве

дисjункциjе (||) и негациjе (!):


на

• оператор && се примењуjе над две буловске вредности, и враћа булов-


ску вредност тачно ако су обе улазне вредности тачне, односно булов-
д

ску вредност нетачно, у супротном,


Ра

• оператор || се примењуjе над две буловске вредности, и враћа булов-


ску вредност тачно ако jе бар jедна улазна вредност тачна, односно
буловску вредност нетачно, у супротном,
• оператор ! се примењуjе над jедном буловском вредношћу, и враћа
њену комплементарну вредност (тj., негациjу).

Пример 5.5. Примена буловских оператора илустрована jе на сл. 5.5.


148 5 Типови података и инструменти апстракциjе у императивноj парадигми

1 ( 2 > 3 ) && ( 1 != 2 ) ; ← наредба генерише буловску вредност нетачно


2 ( 2 > 3 ) | | ( 1 != 2 ) ; ← наредба генерише буловску вредност тачно
3 ! ( 1 == 2 ) ; ← наредба генерише буловску вредност тачно

Слика 5.5 Илустрациjа примене буловских оператора у програмском jезику Ц.

Пример 5.6. Треба приметити да се за израчунавање вредности булов-


ских израза у програмском jезику Ц користи тзв. лењо израчунавање,
коjе ћемо илустровати на следећоj наредби:
(1 < 2) | | (2 > 3 ) ;
Пошто jе вредност прве компоненте израза, (1 < 2), jеднака буловскоj
вредности тачно, може се закључити — због особина дисjункциjе — да
.
ић
ће вредност целе наредбе бити jеднака вредности тачно, без обзира на
ов
буловску вредност друге компоненте израза, (2 > 3). Због тога, да би

а.
се оптимизовало извршавање наредбе, друга компонента израза се не
ат

ан
израчунава. Слично, у наредби:
Гњ

ж
( 2 > 3 ) && ( 1 != 2 ) ;

др
ан

вредност прве компоненте израза, (2 > 3), jеднака je буловскоj вредности


за
нетачно, па се може закључити — због особина конjункциjе — да ће вред-
ил

ност целог израза бити jеднака вредности нетачно, а друга компонента


су
М

израза се не израчунава.
а
1.

ав
02

пр
–2

5.3 Променљиве
а
20

Св

У општем случаjу, променљива представља скуп сукцесивних мемориj-


20

ских локациjа у коjе jе уписана нека вредност. Декларисањем променљи-


а.
©

ве одређуjу се име3 променљиве и тип података вредности променљиве.


иj

Броj мемориjских локациjа додељених променљивоj зависи од њеног типа


рз

података. Због лакшег представљања, у наставку ћемо скупове оваквих


ве

мемориjских локациjа посматрати као целине, без обзира на то колико


мемориjских локациjа садрже.
на

Пример 5.7. Записима:


д
Ра

int x1 , x2 ;
double y ;

3
Различити програмски jезици имаjу различите дефинициjе валидних имена про-
грамских ентитета, попут променљивих, функциjа, итд. Нпр., програмски jезик Ц
осетљив jе на величину слова, тj., имена променљивих „br” и „Br” сматраjу се разли-
читим.
5.3 Променљиве 149

декларишу се променљивe x1 и x2 , коjима се могу доделити цели броjеви,


и променљива y, коjоj се може доделити реални броj двоструке тачности.
Интерна репрезентациjа4 ових променљивих илустрована jе на сл. 5.6(а).

ниже адресе ниже адресе


⇑ ⇑

... ...
Слика 5.6 Интерна ре- ... y 2.71 y
презентациjа декларисања ... ...
и инициjализовања про- ... x2 2 x2
менљивих.
... ...
... x1 1 x1
. ... ...
ић
ов
⇓ ⇓

а.
више адресе више адресе
ат

ан
(а) (б)
Гњ

ж
др
ан

Након декларисања, променљивама се могу доделити вредности. Нпр.,


за
извршавање низа наредби додељивања вредности променљивама:
ил

су

x1 = 1 ;
М

x2 = x1 + 1 ;
а
1.

y = 2.71;
ав
02

пр

може се описати на следећи начин:


–2

• у првоj наредби, променљивоj x1 додељуjе5 се цели броj 1,


а
20

Св

• у другоj наредби, чита6 се вредност променљиве x1 , и увећава за jедан,


20

а резултат сабирања додељуjе се променљивоj x2 .


а.

• у трећоj наредби, променљивоj y додељуjе се реални броj 2, 71.


©

иj

Интерна репрезентациjа ових променљивих након инициjализациjе илу-


рз

стрована jе на сл. 5.6(б). Додељивање вредности променљивама може се


ве

извршити и приликом њиховог декларисања, нпр.:


на

4
Може се приметити да су променљиве коjе су декларисане раниjе у изворном ко̂ду
смештене у мемориjским локациjама на вишим адресама, што рефлектуjе начин на
д

коjи се локалне променљиве смештаjу у позивни стек (в. секциjу 2.7 у 2. поглављу).
Ра

У већини примера разматраних у овом поглављу, однос између адреса на коjима су


смештене променљиве ниjе значаjан. Међутим, у поjединим примерима (нпр., пример
5.26), редослед смештања променљивих биће значаjан за интерпретирање резултата
извршавања ко̂да.
5
Под додељивањем вредности променљивоj подразумева се уписивање вредности у
скуп мемориjских локациjа додељених посматраноj променљивоj.
6
Под читањем вредности променљиве подразумева се читање вредности уписане у
скуп мемориjских локациjа додељених посматраноj променљивоj.
150 5 Типови података и инструменти апстракциjе у императивноj парадигми

int x1 = 1 ;
int x2 = x1 + 1 ;
int y = 2 . 7 1 ;

Наредба додељивања вредности променљивоj примењена у претход-


ном примеру има синтаксичку форму:

ime_promenljive = izraz; (5.1)

где = представља оператор додељивања, и извршава се на следећи начин:


• прво се израчунава вредност подизраза наведеног с десне стране опе-
ратора додељивања,
• израчуната вредност додељуjе се променљивоj чиjе име jе наведено с
леве стране оператора додељивања, .
ић
• а потом се иста вредност прослеђуjе као вредност наредбе додељивања,
ов

а.
што jе илустровано на сл. 5.7. За оператор додељивања (=) се каже да jе
ат

ан
десно асоциjативан, због смера прослеђивања вредности подизраза наве-
Гњ

ж
деног с десне стране оператора.

др
ан

за
ime_promenljive = izraz;
ил

Слика 5.7 Додељивање


су
3 2 1
вредности променљивоj.
М

и прослеђуjе као резултат се израчунава се


вредност наредбе додељуjе вредност
а

додељивања подизраза
1.

ав

променљивоj
02

пр
–2

Пример 5.8. Особина десне асоциjативности оператора додељивања омо-


20

Св

гућава да се jедна вредност додели секвенци променљивих у jедноj на-


20

редби. Нпр., наредба:


а.
©

x1 = x2 = x3 = 1 ;
иj
рз

интерпретира се као:
ве

x1 = ( x2 = ( x3 = 1 ) ) ;
на

тj., поjединачно додељивање вредности променљивама врши се сдесна-


налево, што jе илустровано на сл. 5.8.
д
Ра

Слика 5.8 Илустрациjа


десне асоциjативности
оператора додељивања. x1 = x2 = x3 = 1 ;
5.3 Променљиве 151

Оператори чиjа jе примена над константама била размотрена у сек-


циjи 5.2.1 могу се примењивати и над променљивама. Међутим, постоjе
и оператори коjи се могу примењивати над променљивама, али не и над
константама. Оператор инкрементирања (++) увећава вредност промен-
љиве за 1, а оператор декрементирања (−−) умањуjе вредност промен-
љиве за 1. Њихова особеност jе та да се могу примeњивати као префиксни
и суфиксни оператори, тj., могу се наводити непосредно пре или после
имена променљиве. Нпр., ако се ++ примени као суфиксни оператор:
x++;
вредност променљиве x биће увећана за 1, а вредност наредбе биће jедна-
ка почетноj (не увећаноj) вредности променљиве x. Ако се ++ примени
као префиксни оператор:
++x ; .
ић
вредност променљиве x биће увећана за 1, а вредност наредбе биће jед-
ов

а.
нака увећаноj (не почетноj) вредности променљиве x.
ат

ан
Пример 5.9. Разлика између префиксне и суфиксне примене оператора
Гњ

ж
++ постаjе уочљивиjа у комбинациjи с оператором додељивања. Резултат

др
извршавања наредбе:
ан

за
y = x++;
ил

су

jеднак jе резултату извршавања следеће секвенце наредби:


М

y = x;
1.

ав

x = x + 1;
02

пр

а резултат извршавања наредбе:


–2

y = ++x ;
20

Св
20

jеднак jе резултату извршавања следеће секвенце наредби:


а.
©

x = x + 1;
иj

y = x;
рз

Примена оператора ++ и −− у комбинациjи с оператором додељивања


ве

илустрована jе на сл. 5.9.


д на
Ра

5.3.1 Конвертовање типова атомских података

У практичним применама понекад jе потребно конвертовати вредност


jедног атомског типа података у вредност другог атомског типа података.
Такве конверзиjе се могу поделити по два критериjума. Први критери-
jум се односи на степен контроле коjу програмер има над операциjом
конвертовања. По овом критериjуму, конверзиjе се деле на:
152 5 Типови података и инструменти апстракциjе у императивноj парадигми

1 int x , y ;
2 x = 1;
3 y = x++; ← вредност y jеднака jе 1; вредност x jеднака jе 2
4
5 x = 1;
6 y = ++x ; ← вредност y jеднака jе 2; вредност x jеднака jе 2
7
8 x = 1;
9 y = x −−; ← вредност y jеднака jе 1; вредност x jеднака jе 0
10
11 x = 1;
12 y = −−x ; ← вредност y jеднака jе 0; вредност x jеднака jе 0

Слика 5.9 Илустрациjа примене оператора инкрементирања и декрементирања.

.
ић
• експлицитне конверзиjе, коjе програмер задаjе експлицитним навође-
ов

њем оператора конвертовања,

а.
ат

• имплицитне конверзиjе, коjе се извршаваjу аутоматски, без експлицит-

ан
ног захтева од стране програмера.
Гњ

ж
др
Други критериjум се односи на губитак прецизности с коjом jе конвер-
ан

тована вредност представљена у односу на изворну вредност. По овом


за
критериjуму, конверзиjе се деле на:
ил

су

• конверзиjе с губитком прецизности,


М

• конверзиjе без губитка прецизности.


а
1.

ав

У општем случаjу, губитак прецизности jавља се при конвертовању вред-


02

пр

ности типа података веће прецизности у вредност типа података мање


–2

прецизности.
а
20

Св

Пример 5.10. Jедан од случаjева у коjима се извршава имплицитно кон-


20

вертовање вредности jе кад се променљивоj jедног атомског типа пода-


а.

така додели вредност другог атомског типа података. Нпр., у наредби:


©

иj

double r = 2 ;
рз

цели броj 2 додељуjе се променљивоj коjа jе декларисана као реални броj.


ве

Да би се ова наредба реализовала, извршава се имплицитно конвертова-


ње целог броjа 2 у реални броj 2, 0, коjи се потом додељуjе променљивоj
на

r. Осим промене типа података, ова конверзиjа не генерише губитак пре-


д

цизности с коjом jе конвертована вредност представљена у односу на


Ра

изворну вредност.
Међутим, у наредби:
int c = 2 . 7 1 ;
реални броj 2, 71 додељуjе се променљивоj коjа jе декларисана као цели
броj. Да би се ова наредба реализовала, извршава се имплицитно кон-
вертовање реалног броjа 2, 7 у цели броj 2, занемаривањем децималног
5.3 Променљиве 153

дела изворног реалног броjа. Ова конверзиjа се разликуjе од претход-


не, jер генерише губитак прецизности с коjом jе конвертована вредност
представљена у односу на изворну вредност.

Пример 5.11. Ко̂д приказан на сл. 5.10 представља пример некоректног


израчунавања просечне вредности два цела броjа. Пошто су променљиве
a и b декларисане као целоброjне, резултат извршавања операциje де-
љења у 3. линиjи ко̂да такође jе цели броj7 . Другим речима, вредност
подизраза:
(a + b) / 2
jеднака jе целом броjу 1. Приликом додељивања израчунате целоброj-
не вредности променљивоj c, врши се њено имплицитно конвертовање у
реални броj, тj., променљивоj c се додељуjе вредност 1, 0.
.
ић
ов

а.
1 int a = 1 ;
ат

2 int b = 2 ;

ан
3 double c = ( a + b ) / 2 ; ← променљивоj c додељуjе се вредност 1, 0
Гњ

ж
др
Слика 5.10 Пример некоректног израчунавања просечне вредности два цела броjа.
ан

за
ил

су
Ако желимо да се променљивоj c додели вредност коjа одговара сред-
М

њоj вредности целоброjних променљивих a и b, довољно jе да именилац


а

или броjилац разломка a+b


2 буду експлицитно конвертовани у реaлне бро-
1.

ав

jеве, што jе илустровано на сл. 5.11.


02

пр
–2

1 int a = 1 ;
20

Св

2 int b = 2 ;
20

3 double c ;
а.

4 броjилац jе експлицитно конвертован у реални броj


©

5
иj

6 c = ( double ) ( a + b ) / 2 ; ← променљивоj c додељуjе се вредност 1, 5


рз

7
8 c = ( a + b ) / 2.0 ; ← променљивоj c додељуjе се вредност 1, 5
ве

9
10 именилац jе наведен као реални броj
д на
Ра

Слика 5.11 Примери коректног израчунавања просечне вредности два цела броjа.

7
Зависност резултата примене оператора дељења од врсте броjева над коjима jе опе-
ратор примењен обjашњена jе у примеру 5.2.
154 5 Типови података и инструменти апстракциjе у императивноj парадигми

5.4 Функциjе и условно извршавање

У програмском jезику Ц, дефинициjа функциjе састоjи се од деклара-


циjе функциjе и тела функциjе. Декларациjу функциjе чине:
• тип података повратне вредности функциjе (ако функциjа не враћа
вредност8 , наводи се тип података void),
• име функциjе,
• низ декларациjа улазних аргумената функциjе, наведен у облим загра-
дама (ако функциjа не прихвата улазне аргументе, наводе се празне
обле заграде).
Након декларациjе функциjе следи тело функциjе, наведено у витича-
стим заградама. У телу функциjе израчунава се повратна вредност функ-
.
циjе, и саопштава наредби return, коjа прекида извршавање функциjе, а
ић
саопштену вредност прослеђуjе као повратну вредност функциjе. У телу
ов

функциjе коjа не враћа вредност, навођење наредбе return ниjе неопход-

а.
но, а ако се наредба return ипак наведе, не прослеђуjе jоj се повратна
ат

ан
вредност.
Гњ

ж
Пример 5.12. Дефинишимо функциjу коjа прихвата реални броj x, и ге-

др
нерише вредност x2 , тj.:
ан

за
f (x) = x2 , x ∈ R . (5.2)
ил

су

Дефинициjа задате функциjе приказана jе на сл. 5.12, a њена синтак-


М

сичка структура разложена jе на сл. 5.13.


а
1.

ав
02

пр

1 double f ( double x ) {
–2

2 return x ∗ x ;
а

3 }
20

Св
20

Слика 5.12 Функциjа коjа прихвата реални броj x, и израчунава вредност x2 .


а.
©

иj
рз

Синтаксичка структура наредбе условног извршавања дата jе на сл.


ве

5.14, при чему jе део наредбе коjи почиње резервисаном речjу else опцион.
Ова наредба се извршава на очекивани начин: ако jе вредност буловског
на

израза тачна, извршава се прва наредба; у супротном, извршава се друга


д

наредба.
Ра

Пример 5.13. Дефинишимо функциjу коjа прихвата два реална броjа, и


као резултат враћа већи од њих, тj.:

f (a, b) = max{a, b}, за a, b ∈ R . (5.3)


8
Aко функциjа не враћа вредност, то значи да се резултати њеног извршавања ре-
флектуjу кроз бочне ефекте.
5.4 Функциjе и условно извршавање 155

тип података повратне вредности функциjе


име функциjе
тип података улазног аргумента
име улазног аргумента
почетак тела функциjе

double f ( double x) {
return x * x;
}

повратна вредност функциjе


краj тела функциjе

Слика 5.13 Синтаксичка структура дефинициjе функциjе дате на сл. 5.12.



. 
ић
i f ( bulovski_izraz )
ов
naredba1

а.
else
ат

ан
naredba2
 
Гњ

ж
др
Слика 5.14 Синтаксичка структура наредбе условног извршавања.
ан

за
ил

Дефинициjа задате функциjе дата jе на сл. 5.15. Тело функциjе чини


су
М

наредба условног извршавања у коjоj се посматра услов a > b. Ако jе


а

услов задовољен, тj., ако jе a већe од b, функциjа враћа вредност улазног


1.

ав

аргумента a. У супротном, ако jе a мање од или jеднако b, функциjа


02

пр

враћа вредност улазног аргумента b.


–2

а
20

Св

1 double maks2 ( double a , double b ) {


20

2 i f (a > b)
а.

3 return a ;
©

4
иj

else
5 return b ;
рз

6 }
ве

Слика 5.15 Дефинициja функциje коjа прихвата два реална броjа, и као резултат
на

враћа већи од њих.


д
Ра

Пример 5.14. Дефинишимо функциjу коjа прихвата три реална броjа, и


као резултат враћа наjвећи од њих, тj.:

f (a, b, c) = max{a, b, c}, за a, b, c ∈ R . (5.4)


156 5 Типови података и инструменти апстракциjе у императивноj парадигми

Jедна од могућих дефинициjа ове функциjе дата jе на сл. 5.16. Тело


функциjе чини наредба условног извршавања коjа садржи две угнежђе-
не наредбе условног извршавања, и може се интерпретирати на следећи
начин. Прво се пореде вредности аргумената a и b. Ако важи a > b, то
значи да вредност b сигурно ниjе максимална, па се у наредном кораку
пореде вредности аргумената a и c, а као резултат се враћа већа вред-
ност. Ако не важи a > b, то значи да вредност a можемо да искључимо
из поређења, па се у наредном кораку пореде вредности аргумената b и
c, а као резултат се враћа већа вредност.

1 double maks3 ( double a , double b , double c ) {


2 i f (a > b)
3 if (a > c)
4 return a ;
.
ић
5 else
6 return c ;
ов

а.
7 else
ат

ан
8 i f (b > c )
9 return b ;
Гњ

ж
10 else

др
11 return c ;
ан

12 } за
ил

су

Слика 5.16 Дефинициja функциje коjа прихвата три реална броjа, и као резултат
М

враћа наjвећи од њих.


а
1.

ав
02

Други начин да се дефинише ова функциjа приказан jе на сл. 5.17.


пр

У овоj дефинициjи позива се функциjа maks2 (претходно дефинисана у


–2

примеру 5.13), коjа прихвата два броjа, и као резултат враћа већи од
а
20

Св

њих. У првом позиву, функциjи maks2 саопштаваjу се аргументи b и c.


20

Резултат овог позива саопштава се — заjедно с вредношћу a — као улазни


а.

аргумент другог позива функциjе maks2.


©

иj
рз

1 double maks3 ( double a , double b , double c ) {


ве

2 return maks2 ( a , maks2 ( b , c ) ) ;


3 }
д на

Слика 5.17 Друга дефинициja функциje коjа прихвата три реална броjа, и као ре-
Ра

зултат враћа наjвећи од њих.

Пример 5.15. Дефинишимо функциjу коjа прихвата два цела броjа, и


проверава да ли jе први броj дељив другим.
Дефинициjа задате функциjе дата jе на сл. 5.18. Ово решење се за-
снива на правилу да jе броj x дељив броjем y ако и само ако jе остатак
5.4 Функциjе и условно извршавање 157

целоброjног дељења x с y jеднак нули:

x % y == 0. (5.5)

Међутим, ако jе вредност броjа y jеднака нули, израчунавање буловског


израза (5.5) изазива грешку у извршавању програма, jер дељење нулом
ниjе дозвољено. Да бисмо превазишли оваj проблем, у приказаноj функ-
циjи се прво проверава да ли jе вредност улазног аргумента y jеднака
нули. Ако jесте, извршавање функциjе се прекида, а повратна вредност
функциjе jеднака jе нули, што индикуjе да броj x ниjе дељив броjем y. У
супротном, проверава се услов (5.5).

1 int d e l j i v ( int x, int y) {


2 i f ( y == 0 )
.
ић
3 return 0 ;
ов
4 i f ( x % y == 0 )

а.
5 return 1 ;
ат

ан
6 else
7 return 0 ;
Гњ

ж
8 }

др
ан

за
Слика 5.18 Дефинициja функциje коjа проверава дељивост jедног целог броjа дру-
ил

гим целим броjем.


су
М

Задата функциjа се може дефинисати и концизниjе, као што jе при-


1.

ав

казано на сл. 5.19, при чему се примењуjе само jедна наредба условног
02

пр

извршавања заснована на следећем буловском изразу:


–2

((y != 0) && (x % y == 0)) . (5.6)


20

Св
20

Преводилац израчунава израз (5.6) слева-надесно. Ако jе вредност аргу-


а.

мента y jеднака нули, први елемент конjункциjе — тj., подизраз (y != 0)


©

иj

— има вредност нетачно, из чега следи да jе вредност целог буловског


рз

израза (5.6) нетачна, па се други елемент конjункциjе — тj., подизраз


(x % y == 0) — не израчунава, тj., не покушава се дељење нулом. У су-
ве

протном, ако jе вредност аргумента y различита од нуле, први елемент


на

конjункциjе има вредност тачно, па jе вредност целог израза одређена


вредношћу другог елемента конjункциjе. Може се приметити да jе редо-
д

след навођења елемената у изразу (5.6) важан, за разлику од математике,


Ра

где jе операциjа конjункциjе комутативна. Да jе примењен следећи бу-


ловски израз:
((x % y == 0) && (y != 0)) , (5.7)
прво би се израчунавао подизраз (x % y == 0), чиме би грешка узроко-
вана покушаjем дељења нулом и даље била актуелна. Због тога, решење
приказано на сл. 5.19 не представља пример добре програмерске праксе,
158 5 Типови података и инструменти апстракциjе у императивноj парадигми

jер се ослања на претпоставку одређеног редоследа израчунавања делова


израза на истом хиjерархиjском нивоу, тj., резултат извршавања наредбе
зависи од специфичних дизаjнерских аспеката конкретног преводиоца9 .

1 int d e l j i v ( int x , int y ) {


2 i f ( ( y != 0 ) && ( x % y == 0 ) )
3 return 1 ;
4 else
5 return 0 ;
6 }

Слика 5.19 Друга дефинициja функциje коjа проверава дељивост jедног целог броjа
другим целим броjем.

.
ић
ов

Пример 5.16. Посматраjмо буловски израз у наредби условног извршава-

а.
ат

ња приказаноj на сл. 5.20, у коjем jе уместо релационог оператора jеднако

ан
(==) примењен оператор доделе (=):
Гњ

ж
др
(x = 1).
ан

за
Оваj израз садржи, у ствари, операциjу додељивања вредности 1 про-
ил

менљивоj x, што значи да jе његова вредност10 такође jеднака 1. Пошто


су

се свака ненулта вредност интерпретира као буловска вредност тачно,


М

посматрани буловски услов увек jе испуњен, без обзира на изворну вред-


а
1.

ност променљиве x. Као последица, ко̂д приказан на сл. 5.20 сматра се


ав

синтаксички исправним, иако резултат његовог извршавања ниjе очеки-


02

пр

ван — променљивоj x се додељуjе вредност 1, а променљивоj y вредност


–2

2.
а
20

Св
20

1 int x = 0 ;
а.
©

2 int y ;
иj

3 i f ( x = 1)
рз

4 y = 2;
5 else
ве

6 y = 3 ; ← ова наредба се не извршава, без обзира на изворну вредност x


на

Слика 5.20 Пример употребе оператора додељивања у буловском изразу.


д
Ра

9
Ово jе размотрено у 1. поглављу (в. пример 1.3) и 2. поглављу (в. примерe 2.6 и
2.10).
10
Десна асоциjативност оператора додељивања обjашњена jе у секциjи 5.3 овог по-
главља.
5.5 Низови 159

5.5 Низови

Низ jе уређена секвенца података одређеног типа. Приликом деклари-


сања низа спецификуjу се:
• тип података елемената коjе низ садржи,
• броj елемената коjе низ садржи.
У основи, низови су линеарне структуре података, као и листе у програм-
ском jезику Ракет. Међутим, за разлику од листи, коjе могу да садрже
елементе различитих типова података, низови могу да садрже само еле-
менте декларисаног типа података.

Пример 5.17. Декларисање низова и приступ елементима низа илустро-


вани су у ко̂ду приказаном на сл. 5.21. У првоj линиjи ко̂да, a се декла-
.
ић
рише као низ коjи садржи дванаест целоброjних елемената. Извршавање
ов
ове декларациjе подразумева да се у мемориjи одвоjи дванаест сукце-

а.
сивних мемориjских блокова11 за смештање елемената низа a. Сваком
ат

ан
елементу низа додељуjе се индекс коjи означава позициjу елемента у ни-
Гњ

ж
зу. Првом елементу низа додељуjе се индекс 0, другом елементу индекс

др
1, итд. (в. сл. 5.22(а)).
ан

Приступање елементу низа a коjем jе додељен индекс i врши се син-


за
таксичким записом:
ил

a[ i ]. (5.8)
су
М

Наредбама наведеним у другоj и трећоj линиjи ко̂да, елементима a[0] и


а
1.

ав

a[2] додељуjу се, респективно, вредности 3 и 1. У последњоj наредби, вред-


02

ности елемената a[0] и a[2] се читаjу и сабираjу, а резултат се додељуjе


пр

елементу a[5] (в. сл. 5.22(б)).


–2

Важно jе приметити да остали елементи низа a имаjу вредности коjе


а
20

Св

су одређене садржаjима мемориjских локациjа у тренутку декларисања


20

низа. Пошто садржаjи мемориjских локациjа зависе од контекста у коjем


а.

се програм извршава, ове вредности немаjу везе са семантиком програ-


©

иj

ма, па добра пракса програмирања подразумева да се сви елементи низа


експлицитно инициjализуjу пре употребе.
рз
ве

1 int a [ 1 2 ] ;
на

2 a [ 0 ] = 3;
д

3 a [ 2 ] = 1;
Ра

4 a[5] = a[0] + a [2];

Слика 5.21 Декларисање низа и приступање његовим елементима.

11
За сваки елемент низа одваjа се по jедан мемориjски блок. Сви блокови су jеднаких
величина.
160 5 Типови података и инструменти апстракциjе у императивноj парадигми

ниже адресе ниже адресе ниже адресе


⇑ ⇑ ⇑

... ... ...


... a a a
a[0] a[0] 3 a[0] 3
a[1] ... a[1] ... a[1] 8
a[2] ... a[2] 1 a[2] 1
a[3] ... a[3] ... a[3] 7
a[4] ... a[4] ... a[4] 6
a[5] ... a[5] 4 a[5] 4
a[6] ... a[6] ... a[6] 9
a[7] ... a[7] ... a[7] 2
a[8] ... a[8] ... a[8] 5
a[9] ... a[9] ... a[9] 8
a[10] ... a[10] ... a[10] 0
a[11] ... a[11] ... a[11] 1


.
⇓ ⇓
ић
више адресе више адресе више адресе
ов

а.
(а) (б) (в)
ат

ан
Слика 5.22 Илустрациjа стања у мемориjи релевантних за примере (а,б) 5.17 и (в)
Гњ

ж
5.18.

др
ан

Пример 5.18. Елементима низа a могу се доделити вредности приликом


за
ил

декларисања низа, нпр.:


су
М

int a [ 1 2 ] = { 3 , 8 , 1 , 7 , 6 , 4 , 9 , 2 , 5 , 8 , 0 , 1 } ;
а

а резултуjуће стање у мемориjи илустровано jе на сл. 5.22(в). Низ a jе


1.

ав

декларисан и интерно представљен као линеарна структура, при чему се


02

пр

сваком елементу низа може приступити преко његовог индекса, што jе


–2

илустровано на сл. 5.23.


а
20

Св
20

а.

0 1 2 3 4 5 6 7 8 9 10 11
©

иj

h i
a= 3 8 1 7 6 4 9 2 5 8 0 1
рз
ве

a [3] a [6] a [9]


на

Слика 5.23 Приступ елементима jеднодимензионалног низа.


д
Ра

Низови се могу декларисати и као вишедимензионални. Нпр., jедноди-


мензионални низ приказан на сл. 5.23 може се представити као дводимен-
зионални низ (тзв. матрица) организован у три врсте и четири колоне:
int m[ 3 ] [ 4 ] = { { 3 , 8 , 1 , 7 } ,
{6 , 4 , 9 , 2} ,
{5 , 8 , 0 , 1}};
5.5 Низови 161

што jе илустровано на сл. 5.24. Елементима матрице се приступа помоћу


два индекса коjи респективно представљаjу врсту и колону матрице у
коjима се елемент налази, тj., m[i][ j] представља елемент матрице m коjи
се налази на пресеку врсте коjоj jе додељен индекс i и колоне коjоj jе
додељен индекс j.

0 1 2 3
 
0 3 8 1 7
 
 
m = 1
6 4 9 2 

 
2 5 8 0 1

.
ић
m [2][1] m [1][2] m [0][3]
ов

а.
ат

Слика 5.24 Приступ елементима дводимензионалног низа (тj., матрице).

ан
Гњ

ж
Међутим, иако се декларациjе jеднодимензионалног низа приказаног

др
на сл. 5.23 и дводимензионалног низа приказаног на сл. 5.24 формално
ан

за
разликуjу, важно jе приметити да су оба низа интерно представљена на
ил

исти начин — као секвенца сукцесивних мемориjских блокова приказана


су
М

на сл. 5.22(в).
а
1.

ав

У општем случаjу, матрица m коjа садржи M врста и N колона:


02

пр

0 1 ... N −1
–2

 
···
а

0 m0,0 m0,1 m0,N−1


20

Св

1  m1,0 m1,1 ··· m1,N−1 


(5.9)
20

m= .  .. .. .. .. ,
 
..  . . . .
а.


©

M − 1 mM−1,0 mM−1,1 ··· mM−1,N−1


иj
рз

интерно се представља исто као и низ коjи садржи M · N елемената:


ве

a = m0,0 , m0,1 , . . . , m0,N−1 , m1,0 , m1,1 , . . . , m1,N−1 , . . . , mM−1,0 , mM−1,1 , . . . , mM−1,N−1 ,


на

| {z }| {z } | {z }
прва врста друга врста M -та врста
(5.10)
д
Ра

при чему се елемент m[i][ j], коjи се у матрици m налази на пресеку врсте
коjоj jе додељен индекс i и колоне коjоj jе додељен индекс j, у низу a
налази на позициjи коjоj одговара индекс i · N + j.

Пример 5.19. Jеднодимензионални низ приказан на сл. 5.23 и дводимен-


зионални низ приказан на сл. 5.24 могу се представити као тродимензи-
онални низ димензиjе [2 × 2 × 3]:
162 5 Типови података и инструменти апстракциjе у императивноj парадигми

int m [ 3 ] [ 2 ] [ 2 ] = { { { 3 , 8} ,
{1 , 7}} ,
{{6 , 4} ,
{9 , 2}} ,
{{5 , 8} ,
{0 , 1}}};
што jе илустровано на сл. 5.25. Елементима овог низа приступа се помоћу
три индекса коjи представљаjу координате у дискретноj тродимензионал-
ноj структури низа. Притом, и даље важи да се оваj тродимензионални
низ интерно представља на исти начин као и низови приказани на сл.
5.23 и 5.24 — секвенцом сукцесивних мемориjских блокова приказаном
на сл. 5.22(в).

.
ић
 
ов

 5

а.
8 
ат

i
 

ан
с 0 1
д ек
Гњ

ин

ж
 
6 4

др
 
ан

9 2
  за
индекс k

ил

су
 
индекс j

3 8
М

 
1
а

7
 
1.

ав
02

пр
–2

m [0][1][1] m [1][1][0] m [2][0][1]


а
20

Св

Слика 5.25 Приступ елементима тродимензионалног низа.


20

а.
©

иj
рз
ве

5.5.1 Стрингови
на

У програмском jезику Ц, стрингови су специjална врста низова, коjом


д

се представљаjу текстуални подаци. Формално, стринг се дефинише као


Ра

низ симбола коjи се завршава специjалним симболом12 ’\0’. Jедан од на-

12
У програмском jезику Ц, свака симболичка константа представљена jе целоброj-
ним машинским ко̂дом (в. секциjу 5.2). Специjални симбол ’\0’ одговара целоброjноj
вредности 0.
5.5 Низови 163

чина за представљање вредности стрингова у изворном ко̂ду jе навођење


низа симбола између наводника13 (").

Пример 5.20. Текстуални податак „robot“ се у изворном ко̂ду може пред-


ставити стрингом:
" robot "
чиjа jе интерна репрезентациjа приказана на сл. 5.26. Броj мемориjских
локациjа одвоjених за смештање овог стринга за jедан jе већи од бро-
jа „видљивих“ симбола у стрингу, jер jе додатна мемориjска локациjа
одвоjена за смештање специjалног симбола ’\0’, коjи означава завршетак
стринга.

ниже адресе
.
ић

ов

а.
...
ат

ан
s
s[0] ’r’
Гњ

’o’

ж
s[1]
s[2] ’b’

др
s[3] ’o’
ан

s[4] ’t’ последњи елемент стринга je ’\0’


за
s[5] ’\0’
...
ил

су
М


а

више адресе
1.

ав
02

пр

Слика 5.26 Интерна репрезентациjа стринга.


–2

а
20

Следеће декларациjе стрингова су еквивалентне:


Св
20

char s1 [ ] = " robot " ;


а.
©

char s2 [ ] = {" robot " } ;


иj

char s 3 [ ] = { ’ r ’ , ’ o ’ , ’ b ’ , ’ o ’ , ’ t ’ , ’ \0 ’ } ;
рз

char s4 [ 6 ] = { ’ r ’ , ’ o ’ , ’b ’ , ’ o ’ , ’ t ’ } ;
ве

тj., интерне репрезентациjе ових стрингова исте14 су као репрезентациjа


приказана на сл. 5.26. Приликом декларисања низова s1 , s2 и s3 , њихови
на

капацитети (тj. броjеви елемената у низу) нису експлицитно наведени, jер


д

су имплицитно одређени вредностима коjима су елементи низова иници-


Ра

jализовани. Низовима s1 и s2 додељени су стрингови (тj., низови симбола


наведени под наводницима), што значи да се специjални симбол ’\0’ на

13
Исто као у програмском jезику Ракет, за представљање вредности стрингова кори-
сте се наводници из енглеског правописа, а не српског.
14
Прецизниjе речено, интерне репрезентациjе ових стрингова садржаjно су исте, али
су смештене на различитим мемориjским адресама.
164 5 Типови података и инструменти апстракциjе у императивноj парадигми

краjу стринга подразумева, и нема потребе да се експлицитно наводи. Ни-


зу s3 додељен jе низ засебно наведених симбола коjи представља стринг,
jер jе специjални симбол ’\0’ наведен као последњи елемент. Низ s4 jе
инициjализован сличним записом, али jе специjални симбол ’\0’ изоста-
вљен, jер jе у декларациjи низа s4 експлицитно наведен његов капацитет,
коjи jе за jедан већи од броjа додељених симбола, па jе последње место
у низу инициjализовано вредношћу ’\0’.
Mеђутим, следеће декларациjе представљаjу низове симбола, али не и
стрингове:
char s 5 [ 5 ] = " r o b o t " ;
char s 6 [ 5 ] = { ’ r ’ , ’ o ’ , ’ b ’ , ’ o ’ , ’ t ’ } ;
jер су s5 и s6 експлицитно декларисани као низови коjи садрже по пет сим-
бола, тj., ниjе предвиђено место за специjални симбол ’\0’, коjи означава
.
ић
завршетак стринга. Изостављање симбола ’\0’ може да изазове неочеки-
ване последице приликом извршавања програма, што jе илустровано у
ов

а.
примеру 5.26.
ат

ан
Гњ

ж
др
5.6 Показивачи
ан

за
ил

Показивач jе променљива коjа садржи мемориjску адресу друге про-


су
М

менљиве, и може се примењивати за посредни приступ променљивоj на


а

коjу показуjе. Приликом декларисања показивача спецификуjе се тип


1.

ав

података променљиве на коjу може да показуjе.


02

пр

Пример 5.21. Декларисање показивача и посредно приступање промен-


–2

љивоj на коjу показуjе илустровани су у ко̂ду приказаном на сл. 5.27. У


а
20

Св

првоj линиjи ко̂да, променљива x се декларише као цели броj, у мемориjи


20

се одваjа простор за смештање њене вредности, и додељуjе jоj се вредност


а.

1 (в. сл. 5.28(a)). У другоj линиjи ко̂да, променљива p се декларише као


©

иj

показивач на цели броj, навођењем симбола * испред имена променљиве.


рз

У мемориjи се одваjа простор за смештање вредности показивача p, али


у посматраном тренутку оваj показивач jош ниjе инициjализован, тj., jош
ве

не показуjе ни на jедну променљиву (в. сл. 5.28(б)). Додељивање вред-


на

ности показивачу p врши се наредбом у трећоj линиjи ко̂да. Применом


унарног оператора & над променљивом x добиjа се адреса мемориjске
д

локациjе на коjоj jе променљива x смештена. Ова адреса се додељуjе по-


Ра

казивачу p, тj., p показуjе на x (в. сл. 5.28(в)). У последњоj наредби, при-


меном унарног оператора * над показивачем p врши се посредни приступ
променљивоj x, и додељуjе jоj се вредност 2 (в. сл. 5.28(г)).

Пример 5.22. У различитим тренуцима извршавања програма, покази-


вач може да показуjе на различите променљиве коjе одговараjу типу
података за коjи jе показивач декларисан, што jе илустровано у ко̂ду
5.7 Веза између низова и показивача 165

1 int x = 1 ; ← (а) декларисање променљиве x


2 i n t ∗p ; ← (б) декларисање показивача p
3 p = &x ; ← (в) p показуjе на x
4 ∗p = 2 ; ← (г) x посредно добиjа вредност 2

Слика 5.27 Декларисање показивача и посредно приступање променљивоj на коjу


показуjе.

ниже адресе ниже адресе ниже адресе ниже адресе


⇑ ⇑ ⇑ ⇑

... ... ... ...


... ... p &x p &x p
... ... ... ...
1 1
.
ић
x x 1 x 2 x
... ... ... ...
ов

а.
⇓ ⇓ ⇓ ⇓
ат

ан
више адресе више адресе више адресе више адресе
Гњ

ж
(а) (б) (в) (г)

др
Слика 5.28 Илустрациjа секвенце стања у мемориjи релевантних за ко̂д приказан
ан

на сл. 5.27.
за
ил

су
М

приказаном на сл. 5.29. У првоj линиjи ко̂да, x и y се декларишу као


а

целоброjне променљиве, p1 и p2 као показивачи, у мемориjи се одваjа


1.

ав

простор за њихово смештање, а целоброjним променљивама се додељуjу


02

пр

вредности (в. сл. 5.30(а)). У другоj линиjи ко̂да, показивачу p1 додељуjе


–2

се адреса на коjоj jе смештена променљива x, тj., p1 показуjе на x (в.


а
20

Св

сл. 5.30(б)). У трећоj линиjи ко̂да, показивачу p2 додељуjе се вредност


показивача p1 , након чега и p2 показуjе на x (в. сл. 5.30(в)). У четвртоj
20

линиjи ко̂да посредно се приступа променљивоj x — преко показивача


а.
©

p2 — и додељуjе jоj се вредност 3 (в. сл. 5.30(г)). У петоj линиjи ко̂да,


иj

показивачу p1 додељуjе се адреса на коjоj jе смештена променљива y, тj.,


рз

p1 показуjе на y (в. сл. 5.30(д)). У последњоj наредби, посредно се читаjу


ве

вредности променљивих x и y, њихов збир се увећава за jедан, а резултат


се посредно додељуjе променљивоj y (в. сл. 5.30(ђ)).
д на
Ра

5.7 Веза између низова и показивача

У програмском jезику Ц, концепти показивача и низова уско су пове-


зани.

Пример 5.23. Нека jе a1 низ целих броjева:


166 5 Типови података и инструменти апстракциjе у императивноj парадигми

1 i n t x = 1 , y = 2 , ∗p1 , ∗ p2 ; ← (а) декларисање променљивих


2 p1 = &x ; ← (в) p1 показуjе на x
3 p2 = p1 ; ← (г) p2 показуjе на x
4 ∗ p2 = 3 ; ← (г) x посредно добиjа вредност 3
5 p1 = &y ; ← (г) p1 показуjе на y
6 ∗ p1 = ∗ p1 + ∗ p2 + 1 ; ← (г) y = y + x + 1

Слика 5.29 Илустрациjа примене показивача.

ниже адресе ниже адресе ниже адресе


⇑ ⇑ ⇑

... ... ...


... p2 ... p2 &x p2
... ... ...
.
ић
... p1 &x p1 &x p1
ов
... ... ...

а.
ат

2 2 2

ан
y y y
... ... ...
Гњ

ж
1 x 1 x 1 x

др
... ... ...
ан

за
ил

⇓ ⇓ ⇓
више адресе више адресе више адресе
су
М

(а) (б) (в)


а
1.

ав

ниже адресе ниже адресе ниже адресе


02

пр

⇑ ⇑ ⇑
–2

... ... ...


20

Св

&x p2 &x p2 &x p2


20

... ... ...


а.
©

&x p1 &y p1 &y p1


иj

... ... ...


рз

2 y 2 y 6 y
... ... ...
ве

3 x 3 x 3 x
на

... ... ...


д
Ра

⇓ ⇓ ⇓
више адресе више адресе више адресе
(г) (д) (ђ)

Слика 5.30 Илустрациjа секвенце стања у мемориjи релевантних за ко̂д приказан


на сл. 5.29.
5.7 Веза између низова и показивача 167

int a1 [ 1 2 ] ;
а променљива a2 показивач на цели броj коjем jе додељена адреса првог
елемента низа a1 (тj., елемента коjем jе додељен индекс 0):
int ∗ a2 = &a1 [ 0 ] ;
У складу с имплементациjом показивача у програмском jезику Ц, вред-
ност a2 + 1 jеднака jе адреси другог елемента низа a1 , вредност a2 + 2
jеднака jе адреси трећег елемента низа a1 , итд. — вредност a2 + i jеднака
jе адреси оног елемента низа a1 коjем jе додељен индекс i. Другим речи-
ма, елементу низа a1 коjем jе додељен индекс i може се приступити на
два начина:
a1 [ i ]
или .
ић
∗ ( a2 + i )
ов

а.
ат

што jе илустровано на сл. 5.31(а).

ан
Гњ

ж
др
ниже адресе ниже адресе
ан

⇑ ⇑ за
ил

... ...
су

... ... a − 2 (приступање ван опсега низа)


М

a[−2]
... ...
а

... a2 ...
a1 [0] a (први елемент низа)
1.

ав

a1 [1] ... a2 + 1 ...


a2 + 2
02

a1 [2] ... ...


пр

... опсег ...


–2

... a2 + i низa a ...


a1 [i]
... ...
а
20

... a2 + 11 ...
Св

a2 [11] a + 11 (последњи елемент низа)


... ...
20

... ... a + 13 (приступање ван опсега низа)


a[13]
а.

... ...
©

иj
рз

⇓ ⇓
више адресе више адресе
ве

(а) (б)
на

Слика 5.31 Илустрациjа концептуалне везе између низова и показивача.


д
Ра

Оваj увид омогућава успостављање концептуалне везе између поjмова


низа и показивача. У општем случаjу, референци a коjа jе дефинисана као
низ додељуjе се само адреса мемориjске локациjе на коjоj jе смештен први
елемент низа, тj., низ a се интерпретира као показивач. Синтаксички
запис a[i], коjим се у изворном ко̂ду приступа елементу низа a коjем
jе додељен индекс i, приликом превођења аутоматски се конвертуjе у
168 5 Типови података и инструменти апстракциjе у императивноj парадигми

запис ∗(a + i), коjим се израчунава адреса мемориjске локациjе на коjоj


jе смештен посматрани елемент низа. Аналогно, ако jе променљива p
дефинисана као показивач, изрази ∗(p + i) и p[i] су еквивалентни.
Jедина разлика између низова и показивача произлази из чињенице
да низови нису променљивe15 , а показивачи jесу, па су изрази p = a и
p + + валидни, а изрази a = p и a + + нису.
Jедна од последица овакве имплементациjе низова у програмском jе-
зику Ц jе та да низови не садрже информациjу о свом капацитету, због
чега њихова примена захтева извесну пажњу.

Пример 5.24. Нека jе a низ капацитета n. Ако jе вредност целоброjне про-


менљиве i мања од нуле или већа од n − 1, изразима a[i] и ∗(a + i) врши
се приступ деловима мемориjе коjи се налазе изван опсега низа a, што
jе илустровано на сл. 5.31(б). Програмски jезик Ц не забрањуjе приступ
.
ић
изван опсега низа, чиме се омогућава да се привидним приступањем еле-
менту низа a промени вредност мемориjских локациjа коjе су додељене
ов

а.
другом низу или другоj променљивоj16 . Оваj ефекат назива се прекора-
ат

ан
чењем бафера, и представља познати сигурносни ризик.
Гњ

ж
Пример 5.25. Нека je низ a декларисан локално у телу функциjе f1 . Тадa

др
се у телу функциjе f1 капацитет низа a може одредити израчунавањем
ан

вредности израза:
за
ил

sizeof(a) / sizeof(a [0]) , (5.11)


су
М

тj., као однос величине мемориjског простора коjи заузима цео низ a и
а

величине мемориjског простора коjи заузима jедан елемент низа a, што


1.

ав

jе илустровано на сл. 5.32.


02

пр
–2

1 int f 1 ( ) {
20

Св

2 int a [ 1 2 ] ;
20

3 int d = sizeof ( a )/ sizeof ( a [ 0 ] ) ;


4 return d ; ← вредност d jеднака jе капацитету низа a
а.
©

5 }
иj
рз

Слика 5.32 Пример контекста у коjем jе могуће израчунати капацитет локално де-
ве

кларисаног низа.
на

Међутим, ако jе низ a саопштен функциjи f2 као улазни аргумент, он


д
Ра

се прослеђуjе17 као показивач на први елемент низа, па вредност израза

15
Формално речено, низови се могу интерпретирати као константни показивачи, тj.,
показивачи чиjа се вредност не може мењати.
16
Нису сви програмски jезици дизаjнирани толико флексибилно у односу на преко-
рачење опсега низа. Нпр., у програмском jезику Jава, низови садрже информациjу о
свом капацитету, а приступање изван опсега низа ниjе дозвољено.
17
Прослеђивање улазних аргумената размотрено jе у секциjи 5.8.
5.7 Веза између низова и показивача 169

(5.11) у телу функциjе f2 ниjе jеднака капацитету низа, већ односу између
величине мемориjског простора коjи заузима показивач a (тj., мемориjска
адреса) и величине мемориjског простора коjи заузима jедан елемент
низа a, што jе илустровано на сл. 5.33.

1 int f 2 ( int a [ ] ) {
2 int d = sizeof ( a )/ sizeof ( a [ 0 ] ) ;
3 return d ; ← вредност d jеднака jе односу величине показивача
4 } (тj., мемориjске адресе) и величине jедног елемента низа a

Слика 5.33 Пример контекста у коjем ниjе могуће израчунати капацитет низа саоп-
штеног функциjи.

.
ић
Пошто низови не садрже информациjу о свом капацитету, приликом
ов

а.
саопштавања низа као улазног аргумента функциjе потребно jе саопшти-
ат

ан
ти и додатни улазни аргумент чиjа вредност одговара капацитету низа18 .
Гњ

Изузетак представљаjу стрингови, чиjи jе капацитет означен посредно,

ж
применом специjалног симбола ’\0’ као индикатора за завршетак стрин-

др
га. Због тога, изостављање симбола ’\0’ може да узрокуjе неочекивано
ан

за
понашање програма.
ил

су

Пример 5.26. Након извршавања следећих декларациjа:


М

char s 1 [ ] = " r o b o t " ;


1.

ав

char s 5 [ 5 ] = " r o b o t " ;


02

пр

s1 представља исправно декларисани стринг коjи се завршава специjал-


–2

ним симболом ’\0’, а s2 представља низ симбола, али не и стринг, jер се


а
20

Св

не завршава специjалним симболом ’\0’. Интерна репрезентациjа ова два


20

низа приказана jе на сл. 5.34(а). Стринг s1 декларисан jе непосредно пре


а.

низа s5 у изворном ко̂ду, али jе у радноj мемориjи смештен непосредно


©

иj

после низа s2 , што jе последица организациjе позивног стека.


Ако се од преводиоца захтева да посматра низ s5 као стринг (нпр., по-
рз

зивањем наредбе за испис стринга), почетак опсега резултуjућег стринга


ве

одређен jе вредношћу адресе почетног елемента низа s5 , а краj опсега


позициjом симбола ’\0’. Пошто jе оваj симбол изостављен у низу s5 , пр-
на

вo наредно поjављивање симбола ’\0’ у радноj мемориjи одговара краjу


д

стринга s1 . Другим речима, низ s5 , декларисан као низ коjи садржи пет
Ра

симбола, биће интерпретиран као стринг "robotrobot", што jе илустрова-


но на сл. 5.34(б).

Пример 5.27. Дефинишимо функциjу коjа прихвата позитивни цели броj


n, и као резултат враћа стринг чиjи садржаj представља облик именице

18
Примери ове праксе дати су у 6. поглављу.
170 5 Типови података и инструменти апстракциjе у императивноj парадигми

ниже адресе ниже адресе


⇑ ⇑

... ...
’r’ s5
опсег ’r’ s5
’o’ ’o’
опсег коjи се
’b’ ’b’
низa s5 ’o’ добиjе ’o’
’t’ кад се ’t’
’r’ s1 низ s5 ’r’ s1
опсег ’o’ интер- ’o’
’b’ претира ’b’
стринга ’o’ ’o’
s1 ’t’ као ’t’
’\0’ стринг ’\0’
... ...


. ⇓
ић
више адресе више адресе
ов

а.
(а) (б)
ат

ан
Слика 5.34 Интерна репрезентациjа стринга и низа симбола.
Гњ

ж
др
ан

човек у номинативу коjи по броjу одговара вредности улазног аргумента


за
n.
ил

Постоjе три облика именице човек у номинативу коjи респективно од-


су
М

говараjу jеднини, паукалу и множини — човек, човека, и људи. Нпр.:


а


1.

ав

1 човек,

02

2, 3, 4 човека,
пр

• 5, 6, 7, . . . , 20 људи,
–2

• 21 човек,
а
20

Св

• 22, 23, 24 човека,


20

• 25, 26, 27, . . . 30 људи, итд.


а.
©

Облик именице коjи одговара броjу n може се одредити на следећи начин:


иj

• Ако jе последња цифра броjа n jеднака 1, а претпоследња ниjе jеднака


рз

1 (укључуjући и случаj кад jе n jеднако 1), одговараjући облик именице


ве

jе човек.
• Ако jе последња цифра броjа n jеднака 2, 3 или 4, а претпоследња ниjе
на

jеднака 1, одговараjући облик именице jе човека.


д

• У свим осталим случаjевима, одговараjући облик именице jе људи.


Ра

Ово правило имплементирано jе функциjом приказаном на сл. 5.35. У


телу функциjе генерише се стринг као резултат, а повратни тип функциjе
декларисан jе као показивач на симбол.
5.8 Пренос улазних аргумената по вредности 171

1 char∗ b r o j _ i m e n i c e ( i n t n ) {
2 i n t pos = n % 1 0 ;
3 int pret = ( n / 10) % 1 0 ;
4 i f ( ( pos == 1 ) && ( p r e t != 1 ) )
5 return " covek " ;
6 e l s e i f ( ( 2 <= pos ) && ( pos <= 4 ) && ( p r e t != 1 ) )
7 return " co ve ka " ;
8 else
9 return " l j u d i " ;
10 }

Слика 5.35 Функциjа коjа враћа стринг чиjи садржаj представља облик именице
човек у номинативу коjи по броjу одговара вредности улазног целоброjног аргумента.

.
ић
5.8 Пренос улазних аргумената по вредности
ов

а.
Сваки пут кад се позове нека функциjа током извршавања програ-
ат

ан
ма, у позивни стек19 привремено се ставља тзв. оквир стека коjи садржи
Гњ

ж
податке релевантне за контекст у коjем jе функциjа позвана, укључуjу-

др
ћи вредности улазних аргумената саопштених функциjи. То значи да се
ан

вредности улазних аргумената привремено копираjу у засебни мемориj-


за
ски блок у оквиру стека, и све промене коjе функциjа формално извршава
ил

над улазним аргументима врше се, у ствари, над копираним вредности-


су
М

ма, при чему изворне вредности улазних аргумената остаjу непромењене.


а

Оваj механизам прослеђивања улазних аргумената назива се преносом по


1.

ав

вредности.
02

пр

Ово правило важи и у специjалном случаjу кад се функциjи саопшти


–2

показивач као улазни аргумент20 , тj., вредност показивача не може бити


а

промењена као последица извршавања функциjе. Међутим, промене из-


20

Св

вршене у телу функциjе над мемориjском локациjом чиjа адреса одгова-


20

ра вредности саопштеног показивача остаjу актуелне и након извршења


а.
©

функциjе.
иj
рз

Пример 5.28. Посматраjмо изворни ко̂д приказан на сл. 5.36. Функциjа


f1 прихвата целоброjну вредност као улазни аргумент, што значи да њено
ве

извршавање неће променити вредност променљиве n локално дефинисане


на

у функциjи f (в. 11. линиjу ко̂да).


С друге стране, функциjа f2 прихвата показивач на целоброjну вред-
д
Ра

ност. Овоj функциjи саопштена jе вредност адресе на коjоj jе променљива


n смештена у радноj мемориjи, чиме jе омогућена посредна промена вред-
ности ове променљиве (в. 12. линиjу ко̂да). Илустрациjа стања позивног
стека за време извршавања функциjе f дата jе на сл. 5.37.
19
Кратки увид у механизам позивног стека пружен jе у 2. поглављу, в. секциjу 2.7.
20
Саопштавање показивача као улазног аргумента функциjе назива се преносом по
референци.
172 5 Типови података и инструменти апстракциjе у императивноj парадигми

1 void f 1 ( i n t a ) {
2 a = a + 1;
3 }
4
5 void f 2 ( i n t ∗b ) {
6 ∗b = ∗b + 1 ;
7 }
8
9 void f ( ) {
10 int n = 1 ;
11 f1 (n ) ; ← функциjа f1 не мења вредност променљиве n (n = 1)
12 f 2 (&n ) ; ← функциjа f2 мења вредност променљиве n (n = 2)
13 }

Слика 5.36 Илустрациjа преноса улазних аргумената по вредности.

.
ић
ов

5.9 Закључне напомене

а.
ат

ан
Гњ

Поглавље ћемо закључити кратком напоменом о синтаксичкоj струк-

ж
тури сложене наредбе и лексичким опсезима променљивих. У програм-

др
ском jезику Ц, употребом витичастих заграда групишу се секвенце де-
ан

за
кларациjа и наредби у сложену наредбу21 , тзв. блок , коjа jе синтаксички
ил

еквивалентна обичноj наредби, при чему се након затворене витичасте


су

заграде не наводе тачка и зарез.


М

Променљиве декларисане у блоку су локалне променљиве. Концепти


а
1.

ав

локалних променљивих и лексичких опсега одговараjу концептима опи-


02

саним у 2. поглављу (в. секциjу 2.5). Лексички опсег локалне променљиве


пр

обухвата део изворног ко̂да од места њеног декларисања до краjа блока.


–2

Блокови могу бити угнежђени у друге блокове, при чему име локалне
а
20

Св

променљиве у угнежђеном блоку сакрива исто име локалне променљиве


20

декларисане у надређеном блоку. Практични аспекти примене блокова и


а.

локалних променљивих детаљниjе су размотрени у 6. поглављу.


©

иj
рз

Библиографскe напоменe:
ве

• Детаљниjа спецификациjа типова података и размотрених инстру-


на

мената апстракциjе у програмском jезику Ц дата jе у првих пет


поглавља библиографског навода [17].
д
Ра

• Стандард за представљање броjева с покретним зарезом дат jе у


библиографском наводу [15].
• Пренос улазних аргумената по вредности, и однос између покази-
вача, стрингова и низова симбола размотрени су у секциjама „6.1

21
Нпр., у овом поглављу, витичасте заграде су коришћене за груписање декларациjа
и наредби коjе чине тело функциjе.
5.9 Закључне напомене 173

ниже адресе ниже адресе


⇑ ⇑

... ...
... ...
оквир 1 a оквир 2 a
стека f1 ... стека f1 ...

пренос
... ...
... ...
оквир ... оквир ...
стека f 1 n стека f 1 n
... ...
... ...

⇓ ⇓
више адресе више адресе
(а)
. (б)
ић
ов
ниже адресе ниже адресе

а.
⇑ ⇑
ат

ан
Гњ

... ...

ж
... ...

др
оквир &n b оквир &n b
ан

стека f2 ... стека f2 ...


за
пренос

... ... пренос


ил

... n=1 ... n=2


су
оквир ... оквир ...
М

стека f &n стека f &n


... ...
а

... ...
1.

ав
02

пр

⇓ ⇓
–2

више адресе више адресе


а
20

Св

(в) (г)
20

Слика 5.37 Илустрациjа стања позивног стека за време извршавања функциjе f


а.
©

дефинисане на сл. 5.36: (a) приликом позивања функциjе f1 , (б) након извршавања
иj

функциjе f1 , (в) приликом позивања функциjе f2 , (г) након извршавања функциjе f2 .


рз
ве

Arrays” и „6.2. Pointers as opaque types” библиографског навода


на

[12].
д

• Смештање локалних променљивих и улазних аргумената у позив-


Ра

ни стек, и прекорачење бафера размотрени су у поглављу „2. Пре-


корачење стека” библиографског навода [9].
174 5 Типови података и инструменти апстракциjе у императивноj парадигми

5.10 Задаци

Задатак 5.1. Дефинишите функциjу коjа прихвата два цела броjа x и y,


и израчунава вредност:
x 1
f (x, y) = + . (5.12)
2 y
Задатак 5.2. Дефинишите сигмоидну функциjу:
ex
s(x) = , (5.13)
ex + 1
где e представља Оjлеров броj (e ≈ 2, 718281828459045). (Савет: в. пример
2.27 у 2. поглављу.)
.
ић
Задатак 5.3. Дефинишите функциjу коjа проверава да ли jе дата година
преступна. Преступна година jе дељива броjем 4, а ако jе дељива броjем
ов

а.
100, мора бити дељива и броjем 400. (Савет: в . пример 2.7 у 2 поглављу.)
ат

ан
Гњ

Задатак 5.4. Дефинишите функциjу коjа прихвата три реална броjа, и

ж
израчунава реципрочну вредност збира два наjвећа броjа.

др
ан

за
Задатак 5.5. Напишите програм коjи декларише низ, и исписуjе вред-
ил

ности његових елемената пре него што их инициjализуjе. Обjасните ре-


су

зултат извршавања овог програма.


М

Задатак 5.6. Дефинишите функциjу коjа прихвата два реална броjа x и


1.

ав

y, и врши међусобну замену њихових вредности. (Савет: в. секциjу 5.8.)


02

пр
–2

а
20

Св
20

а.
©

иj
рз
ве
д на
Ра
Поглавље 6
Итеративни процеси у императивном
програмирању

.
ић
6.1 Увод
ов

а.
ат

ан
У поглављима 3. и 4. размотрили смо две фундаменталне врсте про-
грамских процеса — рекурзивне процесе и итеративне процесе. Обе врсте
Гњ

ж
процеса имплементирали смо рекурзивним функциjама, што jе каракте-

др
ристично за функционално програмирање.
ан

за
Рекурзивни и итеративни процеси заступљени су и у императивном
ил

програмирању, али jе концептуална разлика између њих синтаксички


су

наглашениjа: рекурзивни процеси имплементираjу се рекурзивним функ-


М

циjама, док се за имплементирање итеративних процеса примењуjу спе-


а
1.

ав

циjалне синтаксичке форме, тзв. петље. У овом поглављу размотрићемо


02

два изабране, функционално еквивалентне синтаксичке структуре петље


пр

у програмском jезику Ц, и илустроваћемо њихову примену низом приме-


–2

ра.
а
20

Св
20

а.
©

6.2 Итеративно издваjање цифара из целих броjева


иj
рз

Први синтаксичка структура петље приказана jе на сл. 6.1.


ве

 
на

while ( i z r a z )
д

naredba
Ра

 

Слика 6.1 Синтаксички запис петље.

Ова синтаксичка структура садржи две семантичке компоненте — из-


раз и наредбу — и извршава се кроз следеће кораке:

175
176 6 Итеративни процеси у императивном програмирању

1. Израчунава се вредност израза. Ако jе његова вредност тачна (тj.,


ненулта), прелази се на други корак. У супротном, прелази се на трећи
корак.
2. Извршава се наредба, а потом се враћа на први корак.
3. Излази се из петље, а извршавање програма се наставља од наредбе
коjа непосредно следи петљу.
У овом синтаксичком контексту, израз називамо условом петље, а на-
редбу телом петље, што jе у складу с чињеницом да наредба у петљи
може да буде сложена (тj., секвенца декларациjа и наредби груписаних
применом витичастих заграда). Функционалност петље може се форму-
лисати и у овим терминима: тело петље се извршава све док jе услов
петље задовољен. Свако извршавање тела петље назива се итерациjом
петље.
.
Уобичаjена примена петље подразумева да се израчунавање услова пе-
ић
тље врши над променљивом или скупом променљивих чиjе се вредности
ов

ажурираjу извршавањем тела петље, што jе илустровано у првоj групи

а.
ат

примера, коjи се односе на итеративно издваjање цифара из целих бро-

ан
jева.
Гњ

ж
др
Пример 6.1. Дефинишимо функциjу1 коjа израчунава збир цифара датог
ан

ненегативнoг целог броjа n.


за
Основна идеjа итеративног процеса израчунавања збира цифара датог
ил

су

ненегативнoг целог броjа може се представити на следећи начин. Издва-


М

jање цифара из броjа n врши се од последње цифре ка првоj, и свака


а

издвоjена цифра сабира се са збиром претходно издвоjених цифара. Де-


1.

ав

финициjа функциjе коjа имплементира оваj итеративни процес приказа-


02

пр

на jе на сл. 6.2.
–2

а
20

Св

1 int z b i r _ c i f a r a ( int n ) {
20

2 int z b i r = 0 ;
а.
©

3 while ( n != 0 ) {
иj

4 zbir = zbir + (n % 10);


5 n = n / 10;
рз

6 }
ве

7 return z b i r ;
8 }
д на

Слика 6.2 Функциjа коjа израчунава збир цифара датог ненегативнoг целог броjа.
Ра

На нивоу имплементациjе, издваjање цифара из броjа n и ажурирање


међузбира цифара врше се у петљи. У свакоj итерациjи петље издваjа се
по jедна цифра из броjа n, и сабира с вредношћу променљиве коjа чува

1
Упоредите с примером 3.1 у 3. поглављу.
6.2 Итеративно издваjање цифара из целих броjева 177

Табела 6.1 Приказ итеративног извршавања функциjе дефинисане на сл. 6.2 кад jоj
се саопшти изабрани аргумент.

n zbir

12345 0 ← пре уласка у петљу

1234 5 5





123 4

9







12 3

12

итерациjе

петље
12 14








1 15



.

излазак

ић
0

из петље
ов
0 15 ← након изласка из петље

а.
ат

ан
Гњ

ж
15 ← повратна вредност

др
ан

за
вредност међузбира издвоjених цифара. Петља се извршава све док се
ил

су

не издвоjе све цифре из броjа n.


М

Променљива коjа чува вредност међузбира издвоjених цифара декла-


а

рисана jе пре петље, чиме се постиже да лексички опсег ове променљиве


1.

ав

обухвата лексички опсег петље, тj., омогућаваjу се ажурирање вредности


02

пр

променљиве у телу петље, и приступ променљивоj након изласка из пе-


–2

тље. Приликом декларисања, ова променљива инициjализована jе вред-


а
20

ношћу 0, коjа представља неутрални елемент за сабирање. Након изласка


Св

из петље, вредност ове променљиве jеднака jе збиру цифара броjа n, и


20

прослеђуjе се наредбом return као повратна вредност функциjе. Изврша-


а.
©

вање дате функциjе кад jоj се саопшти изабрани аргумент илустровано


иj

jе у табели 6.1.
рз

Може се приметити да се вредност улазног аргумента n такође мења


ве

у телу петље, а након изласка из петље, његова вредност jеднака jе 0.


Међутим, оваj улазни аргумент пренесен jе по вредности2 , што значи да
на

jе његова вредност привремено копирана у засебни мемориjски блок, и


д

све промене коjе функциjа формално извршава над овим улазним аргу-
Ра

ментом врше се, у ствари, над копираном вредношћу, при чему изворна
вредност улазног аргумента остаjе непромењена.

2
Mеханизам преношења улазних аргумената по вредности обjашњен jе у 5. поглављу
(в. секциjу 5.8).
178 6 Итеративни процеси у императивном програмирању

Пример 6.2. Дефинишимо функциjу3 коjа израчунава броj цифара датог


природног броjа n.
Jедина разлика у поставци овог примера у односу на поставку примера
6.1 jе та што функциjа треба да израчуна броj цифара, уместо њиховог
збира. Да бисмо решили оваj проблем, довољно jе да изворни ко̂д дат
на сл. 6.2 променимо тако да се за сваку цифру издвоjену из броjа n,
међузбир увећава за вредност 1, уместо за вредност издвоjене цифре.
Тако добиjена функциjа приказана jе на сл. 6.3.

1 int b r o j _ c i f a r a ( int n ) {
2 int b r o j = 0 ;
3 while ( n != 0 ) {
4 broj = broj + 1;
5 n = n / 10;
.
ић
6 }
7 return b r o j ;
ов

а.
8 }
ат

ан
Гњ

ж
Слика 6.3 Функциjа коjа израчунава броj цифара датог природног броjа n.

др
ан

за
Пример 6.3. Дефинишимо функциjу4 коjа израчунава производ цифара
ил

су

датог ненегативнoг целог броjа n.


М

Ово jе jош jедна вариjанта проблема представљеног у примеру 6.1 —


а

jедина разлика jе та што функциjа треба да израчуна производ цифара,


1.

ав

уместо њиховог збира. Дефинициjа тражене функциjе приказана jе на сл.


02

пр

6.4, а поступак њеног дефинисања може се описати на следећи начин.


–2

а
20

Св

1 int p r o i z v o d _ c i f a r a ( int n ) {
20

2 i f ( n == 0 )
а.
©

3 return 0 ;
иj

4 int proizvod = 1 ;
5 while ( n != 0 ) {
рз

6 i f ( n % 10 == 0 )
ве

7 return 0 ;
8 proizvod = proizvod ∗ (n % 10);
на

9 n = n / 10;
10 }
д

11 return p r o i z v o d ;
Ра

12 }

Слика 6.4 Функциjа коjа израчунава производ цифара датог ненегативнoг целог
броjа.

3
Упоредите с примером 3.2 у 3. поглављу.
4
Упоредите с примером 3.3 у 3. поглављу.
6.2 Итеративно издваjање цифара из целих броjева 179

Интуитивни приступ решавању овог проблема jе да се изворни ко̂д


дат на сл. 6.2 промени тако што се:
• операциjа сабирања (+) замени операциjом множења (∗),
• променљива коjа чува вредност међупроизвода издвоjених цифара
инициjализуjе вредношћу 1, коjа представља неутрални елемент за
множење.
Међутим, овако добиjена функциjа имала би два недостатка. Први не-
достатак односи се на чињеницу да би функциjа генерисала нетачни ре-
зултат кад jоj се саопшти аргумент чиjа jе вредност jеднака 0 — у том
случаjу, итерациjе петље не би се извршавале, а функциjа би враћала
изворну вредност променљиве коjа чува међупроизвод издвоjених цифа-
ра, тj., 1. Да би се превазишао оваj недостатак, на почетку тела функциjе
додата jе наредба условног извршавања коjа проверава да ли jе вредност
.
ић
улазног аргумента jеднака 0, и ако jесте, прекида извршавање функциjе,
а као повратну вредност прослеђуjе 0.
ов

а.
Други недостатак jе таj што овако добиjена функциjа не би предста-
ат

ан
вљала оптимално решење. У примеру 6.1 било jе неопходно издвоjити
Гњ

ж
све цифре броjа n да би се израчунао њихов збир. У овом примеру, из-

др
дваjање свих цифара броjа n неопходно jе само ако n не садржи цифру
ан

0. У супротном, довољно jе вршити издваjање цифара све док се први


за
пут не издвоjи цифра 0 — тада се може закључити да ће краjњи прои-
ил

звод бити jеднак 0, па нема потребе за даљим издваjањем цифара (тj.,


су
М

даљим итерациjама петље). Због тога jе у тело петље укључен додатни


а

услов за излазак из петље: ако jе издвоjена цифра jеднака 0, прекида се


1.

ав

извршавање функциjе, а као повратна вредност прослеђуjе се 0.


02

пр

Извршавање функциjе приказане на сл. 6.4 кад jоj се саопшти изабра-


–2

ни аргумент илустровано jе у табели 6.2.


а
20

Св
20

Табела 6.2 Приказ итеративног извршавања функциjе дефинисане на сл. 6.4 кад jоj
а.

се саопшти изабрани аргумент.


©

иj

n proizvod
рз

12045 1 ← пре уласка у петљу


ве

1204 5 5

на




итерациjе

120 4
д

20
петље
Ра




12 0 0

излазак из функциjе

0 ← повратна вредност
180 6 Итеративни процеси у императивном програмирању

Пример 6.4. Дефинишимо функциjу5 коjа генерише броj добиjен обрта-


њем редоследа цифара улазног ненегативног целог броjа.
Основна идеjа итеративног процеса обртања редоследа цифара датог
ненегативног целог броjа може се описати на следећи начин. Издваjање
цифара из броjа n врши се од последње цифре ка првоj, и свака издвоjена
цифра додаjе се — у редоследу издваjања — на „десни краj” помоћне
променљиве. Дефинициjа функциjе коjа имплементира оваj итеративни
процес приказана jе на сл. 6.5, а њено извршавање кад jоj се саопшти
изабрани аргумент илустровано jе у табели 6.3.

1 int obrni_redosled ( int n ) {


2 int r = 0 ;
3 while ( n != 0 ) {
4 r = r ∗ 10 + ( n % 1 0 ) ;
.
ић
5 n = n /10;
ов
6 }

а.
7 return r ;
ат

ан
8 }
Гњ

ж
др
Слика 6.5 Функциjа коjа генерише броj добиjен обртањем редоследа цифара улазног
ненегативног целог броjа.
ан

за
ил

су
М

Табела 6.3 Приказ итеративног извршавања функциjе дефинисане на сл. 6.5 кад jоj
1.

ав

се саопшти изабрани аргумент.


02

пр

n r
–2

12345 ← пре уласка у петљу


20

0
Св
20

1234 5 5

а.



©



123 4

54
иj






рз



12 3

543

итерациjе

ве

петље
12 5432





на




1 54321



д



излазак

0

Ра

из петље
0 54321 ← након изласка из петље

54321 ← повратна вредност

5
Упоредите с примером 3.4 у 3. поглављу.
6.3 Итеративна обрада монотоних секвенци броjева 181

Ако се улазни аргумент n завршава секвенцом нула, оне нису садржане


у резултуjућоj вредности, што jе очекивано понашање функциjе у овом
примеру6 .

6.3 Итеративна обрада монотоних секвенци броjева

У овоj секциjи размотрићемо другу синтаксичку структуру петље,


приказану на сл. 6.6, и илустроваћемо њену примену групом примера
коjи се односе на итеративну обраду монотоних секвенци броjева.

 
for ( i z r a z 1 ; i z r a z 2 ; i z r a z 3 )
.
ић
naredba
 
ов

а.
Слика 6.6 Алтернативна синтаксичка структура петље.
ат

ан
Гњ

ж
Треба приметити да ова синтаксичка структура петље не повећава

др
експресивност програмског jезика у односу на синтаксичку структуру
ан

петље приказану на сл. 6.1, већ само омогућава алтернативни синтак-


за
ил

сички запис петље. Синтаксичка структура петље приказана на сл. 6.6


су

еквивалентна jе, у општем случаjу, синтаксичкоj структури приказаноj


М

на сл. 6.7. У практичним применама, избор синтаксичке структуре коjа


а
1.

ав

ће бити примењена зависи у значаjноj мери од афинитета програмера7 .


02

пр

 
–2

izraz1 ;
а
20

Св

while ( i z r a z 2 ) {
naredba
20

izraz3 ;
а.
©

}
 
иj
рз

Слика 6.7 Синтаксичка структура еквивалентна, у општем случаjу, синтаксичкоj


ве

структури приказаноj на сл. 6.6.


д на

Пример 6.5. Дефинишимо функциjу8 коjа израчунава факториjел датог


Ра

ненегативног целог броjа n, тj.:


6
Проблем коjи захтева очување водећих нула у резултуjућоj вредности посматра се
у задатку 3.3 (у 3. поглављу), примеру 4.19 (у 4. поглављу) и примеру 6.11 (у овом
поглављу).
7
Проширење синтаксе коjе не повећава експресивност jезика, већ само олакшава људ-
ско генерисање и интерпретирање изворног ко̂да назива се синтаксичким шећером.
8
Упоредите с примером 3.6 у 3. поглављу.
182 6 Итеративни процеси у императивном програмирању

n · (n − 1) · . . . · 2 · 1, n>0,
f (n) = n! = (6.1)
1, n=0.

Дефинициjа функциjе коjа имплементира итеративни процес израчу-


навања факториjела датог ненегативног целог броjа дата jе на сл. 6.8.
Основна идеjа овог процеса jе да се у итерациjама петље редом генери-
шу и множе броjеви из секвенце целих броjева 2, 3, . . . , n.

1 int f a k t o r i j e l ( int n ) {
2 int f = 1 ;
3 f o r ( i n t i = 2 ; i <= n ; i ++)
4 f = f ∗ i;
5 return f ;
6 }
.
ић
ов
Слика 6.8 Функциja коjа израчунава факториjел датог ненегативног целог броjа.

а.
ат

ан
Исто као у претходним примерима, променљива f , коjа чува вредност
Гњ

ж
међупроизвода, декларисана jе пре петље, чиме се постиже да лексички

др
опсег ове променљиве обухвата лексички опсег петље, тj., омогућаваjу
ан

се ажурирање вредности променљиве у телу петље, и приступ промен-


за
ил

љивоj након изласка из петље. Приликом декларисања, ова променљива


су

инициjализована jе вредношћу 1, коjа представља неутрални елемент за


М

множење. Након изласка из петље, вредност ове променљиве jеднака jе


а
1.

ав

факториjелу броjа n, и прослеђуjе се наредбом return као повратна вред-


02

ност функциjе.
пр

За разлику од претходних примера, у коjима jе мењана вредност ула-


–2

зног параметра, у овоj функциjи декларисана jе додатна променљива за


а
20

Св

потребе генерисања секвенце целих броjева 2, 3, . . . , n. Приликом уласка


20

у петљу, променљива i инициjализуjе се вредношћу 2, и у свакоj итера-


а.

циjи петље прво се користи за ажурирање вредности променљиве f , а


©

иj

потом увећава за 1. Петља се извршава све док jе вредност променљиве


i мања од или jеднака вредности улазног аргумента n. Извршавање дате
рз

функциjе кад jоj се саопшти изабрани аргумент илустровано jе у табели


ве

6.4.
Два детаља у решењу приказаном на сл. 6.8 заслужуjу да буду додатно
на

размотрена:
д
Ра

• Променљива i декларисана jе у петљи, што значи да њен лексички


опсег одговара лексичком опсегу петље, тj., ниjе видљива ван петље.
Ова променљива могла jе бити дефинисана и непосредно пре петље,
тако да њен лексички опсег обухвата део изворног ко̂да од места њеног
декларисања до краjа тела функциjе, при чему би резултат извршава-
ња функциjе остао непромењен. Међутим, пошто у овом примеру нема
потребе да се променљива i користи ван тела петље, добра пракса про-
6.3 Итеративна обрада монотоних секвенци броjева 183

Табела 6.4 Приказ итеративног извршавања функциjе дефинисане на сл. 6.8 кад jоj
се саопшти изабрани аргумент.

n i f

5 - 1 ← пре уласка у петљу

5 2 2





5

3 6






итерациjе

5 4 24

петље
5

5 120







5 6 излазак из петље

.
ић
5 - 120 ← након изласка из петље
ов

а.
ат

ан
120 ← повратна вредност
Гњ

ж
др
грамирања подразумева да се њен лексички опсег ограничи само на
ан

за
петљу, чиме се, у општем случаjу, смањуjе међусобна зависност разли-
ил

читих делова изворног ко̂да, и олакшава његово интерпретирање.


су

• Ако jе вредност улазног аргумента jеднака 0 или 1, ниjедна итера-


М

циjа петље се не извршава, а повратна вредност функциjе jеднака jе


а
1.

ав

инициjалноj вредности променљиве f . Итерациjе петље се извршаваjу


02

само ако jе вредност улазног аргумента већа од или jеднака 2, због


пр

чега jе вредност променљиве i инициjализована вредношћу 2 прили-


–2

ком уласка у петљу. Ова променљива jе могла бити инициjализована


а
20

Св

вредношћу 1, при чему би резултат извршавања функциjе остао непро-


20

мењен, али у том случаjу би извршавање прве итерациjе петље било


а.

непотребно, jер не би мењало вредност променљиве f .


©

иj

Као илустрациjа jеднаких експресивности различитих синтаксичких


рз

записа петљи, на сл. 6.9 и 6.10 приказана су два алтернативна решења


ве

овог проблема.
д на

1 int f a k t o r i j e l ( int n ) {
Ра

2 int f = 1 ;
3 f o r ( i n t i = n ; i >= 2 ; i −−)
4 f = f ∗ i;
5 return f ;
6 }

Слика 6.9 Друга функциja коjа израчунава факториjел датог ненегативног целог
броjа.
184 6 Итеративни процеси у императивном програмирању

1 int f a k t o r i j e l ( int n ) {
2 int f = 1 ;
3 while ( n > 1 ) {
4 f = f ∗ i;
5 n−−;
6 }
7 return f ;
8 }

Слика 6.10 Трећа функциja коjа израчунава факториjел датог ненегативног целог
броjа.

Пример 6.6. Дефинишимо функциjу коjа проверава да ли jе дати при-


.
родни броj n прост. Природни броj jе прост ако jе већи од 1, и ако jе
ић
дељив само броjем 1 и самим собом.
ов

Итеративни процес утврђивања да ли jе дати природни броj n прост

а.
ат

обjашњен jе у 3. поглављу (в. пример 3.8):

ан
Гњ

ж
• Ако важи n = 1, функциjа враћа вредност 0, jер броj 1, по дефинициjи,

др
ниjе прост.
ан

• У супротном, за n ≥ 2, итеративно се пролази кроз секвенцу целих


за
броjева:
ил


(6.2)
су
2, 3, . . . , b nc ,
М

– све док се први пут не наиђе на броj коjи jе делилац броjа n, што
а
1.

значи да n ниjе прост броj, након чега се пролазак кроз секвенцу


ав

(6.2) прекида, а функциjа враћа вредност 0,


02

пр

– или док се не издвоjе сви броjеви из секвенце (6.2), при чему ниjедан
–2

од њих ниjе делилац броjа n, што значи да jе броj n прост, након


а
20

Св

чега функциjа враћа вредност 1.


20

Дефинициjа функциjе коjа имплементира оваj итеративни процес при-


а.
©

казана jе на сл. 6.11. За израчунавање квадратног корена примењена jе


иj

функциjа sqrt9 , коjа прихвата реални броj, а у овом примеру jоj jе саоп-
рз

штена целоброjна вредност, што значи да се приликом њеног позивања


ве

врши имплицитна конверзиjа целог броjа у реални.


на

Пример 6.7. Нека jе n природни броj. Дефинишимо функциjу коjа изра-


чунава n-ти елемент Фибоначиjевог низа.
д

Фибоначиjев низ jе низ целих броjева у коjем су прва два елемента


Ра

jеднака 0 и 1, респективно, а сваки следећи елемент jеднак jе збиру два


елемента коjа му непосредно претходе. У општем случаjу, n-ти елемент
Фибоначиjевог низа може се представити следећом формулом:

9
Функциjа sqrt jе дефинисана у библиотеци математичких функциjа „math.h”. Уко-
лико се за превођење програма коjи садржи ову функциjу примењуjе преводилац gcc,
потребно jе навести опциjу превођења „-lm”.
6.3 Итеративна обрада монотоних секвенци броjева 185

1 int p r o s t ( int n ) {
2 i f ( n == 1 )
3 return 0 ;
4 f o r ( i n t i = 2 ; i <= s q r t ( n ) ; i ++)
5 i f ( n % i == 0 )
6 return 0 ;
7 return 1 ;
8 }

Слика 6.11 Функциja коjа проверава да ли jе дати природни броj n прост.


n − 1, n ≤ 2,
f (n) = (6.3)
f (n − 1) + f (n − 2), n>2.

.
ић
Итеративни процес израчунавања n-тог елемента Фибоначиjевог ни-
за обjашњен jе у 3. поглављу (в. пример 3.7). На сл. 6.12 приказан je
ов

а.
синтаксички запис овог итеративног процеса на програмском jезику Ц.
ат

ан
Гњ

ж
1 int f i b ( int n ) {

др
2 i f ( n <= 2 )
ан

3 return n − 1 ;
за
4 int pret = 0 ;
ил

5 i n t pos = 1 ;
су
М

6 f o r ( i n t i = 3 ; i <= n ; i ++) {
7 i n t p = pos ;
а
1.

ав

8 pos = pos + p r e t ;
9 pret = p ;
02

пр

10 }
–2

11 return pos ;
а

12 }
20

Св
20

Слика 6.12 Функциja коjа израчунава n-ти елемент Фибоначиjевог низа.


а.
©

иj
рз

У наредби условног извршавања наведеноj на почетку тела функци-


jе проверава се да ли jе вредност улазног аргумента jеднака 1 и 2, и
ве

ако jесте, функциjа враћа вредност првог, односно другог елемента Фи-
на

боначиjевог низа. У супротном, у свакоj итерациjи петље израчунава се


по jедан нови елемент Фибоначиjевог низа, почевши од трећег елемента
д
Ра

низа.
У телу функциjе декларисане су две локалне променљиве коjе памте
међурезултате и преносе их из jедне итерациjе петље у наредну:
• променљива pret чува вредност претпоследњег израчунатог елемента
Фибоначиjевог низа,
• променљива pos чува вредност последњег израчунатог елемента Фи-
боначиjевог низа,
186 6 Итеративни процеси у императивном програмирању

а њихове инициjалне вредности одговараjу почетним елементима Фибо-


начиjевог низа, тj., 0 и 1, респективно. У свакоj итерациjи петље, нови
елемент Фибоначиjевог низа израчунава се као збир два последње из-
рачуната елемента, а вредности променљивих pret и pos се ажурираjу.
Након изласка из петље, вредност променљиве pos jеднака jе вредности
n-тог елемента Фибоначиjевог низа, и прослеђуjе се као резултат изврша-
вања функциjе. Извршавање дате функциjе кад jоj се саопшти изабрани
аргумент илустровано jе у табели 6.5.

Табела 6.5 Приказ итеративног извршавања функциjе дефинисане на сл. 6.12 кад
jоj се саопшти изабрани аргумент.

n i pret pos

.
ић
7 - 0 1 ← пре уласка у петљу
ов

7 3 1 1

а.


ат

ан


7 4

1 2



Гњ

ж



7 5

2 3

итерациjе

др

петље
ан

7 6 3 5

 за



ил



7 7

5 8

су



М




7 8 излазак из петље
а
1.

ав

7 - 5 8 ← након изласка из петље


02

пр
–2

8 ← повратна вредност
20

Св
20

а.
©

За потребе ажурирања вредности променљивих pret и pos, у телу пе-


иj

тље декларисана jе помоћна променљива p:


рз

int p = pos ;
ве

pos = pos + p r e t ;
pret = p ;
на

Иста функционалност могла се реализовати без декларисања додатне


д
Ра

променљиве, представљањем тела петље следећом секвенцом наредби:


pos = pos + p r e t ;
p r e t = pos − p r e t ;
а читаоцу се оставља да провери ову тврдњу. Оваj ко̂д jе концизниjи од
постоjећег, али и тежи за људско интерпретирање. У општем случаjу, пи-
сање ко̂да коjи jе тежак за разумевање не спада у добру праксу, посебно
6.4 Итеративна обрада низова целих броjева 187

кад постоjи могућност да се проблем реши интуитивним ко̂дом коjи jе


подjеднако или приближно ефикасан.

6.4 Итеративна обрада низова целих броjева

Трећа група примера односи се на итеративну обраду низова целих


броjева. Пошто низови у програмском jезику Ц не садрже информациjу
о свом капацитету, све функциjе размотрене у овоj секциjи прихватаjу
два аргумента:
( int a [ ] , int n )
тj., низ над коjим се врши обрада, и додатни аргумент чиjа вредност од-
.
ић
говара10 капацитету низа. Због везе11 између показивача и низова, први
улазни аргумент може се декларисати и као показивач на цели броj:
ов

а.
ат

( int ∗a , int n )

ан
Гњ

ж
при чему се улазни аргумент a интерпретира као показивач на први еле-

др
мент низа саопштеног функциjи. Другим речима, приликом саопштавања
ан

низа као улазног аргумента функциjе врши се тзв. пренос по референци


за
(в. секциjу 5.8 у 5. поглављу), што значи да промене извршене у телу
ил

функциjе над елементима низа остаjу актуелне и након извршења функ-


су
М

циjе.
а
1.

ав

Пример 6.8. Дефинишимо функциjу12 коjа израчунава збир елемената


02

низа реалних броjева.


пр

Основна идеjа итеративног процеса израчунавања збира елемената да-


–2

тог низа реалних броjева може се представити на следећи начин. Издва-


20

Св

jање елемената из низа врши се од првог елемента низа ка последњем, и


20

сваки издвоjени елемент сабира се са збиром претходно издвоjених елеме-


а.

ната. Дефинициjа функциjе коjа имплементира оваj итеративни процес


©

иj

приказана jе на сл. 6.13.


рз

У свакоj итерациjи петље издваjа се по jедан елемент низа, и сабира с


вредношћу променљиве коjа чува вредност међузбира претходно издво-
ве

jених елемената. Петља се извршава све док се не издвоjе сви елементи


на

низа. Након изласка из петље, вредност ове променљиве jеднака jе збиру


елемената датог низа, и прослеђуjе се наредбом return као повратна вред-
д

ност функциjе. Извршавање дате функциjе кад jоj се саопште изабрани


Ра

аргументи илустровано jе у табели 6.6.

10
Од програмера коjи позива функциjу се очекуjе да вредност аргумента n одговара
стварном капацитету низа a.
11
В. секциjу 5.7 у 5. поглављу.
12
Упоредите сa сложениjим примером 4.20 у 4. поглављу.
188 6 Итеративни процеси у императивном програмирању

1 double z b i r _ n i z a ( double a [ ] , i n t n ) {
2 int s = 0 ;
3 f o r ( i n t i = 0 ; i < n ; i ++)
4 s = s + a[ i ];
5 return s ;
6 }

Слика 6.13 Функциjа коjа израчунава збир елемената низа реалних броjева.

Табела 6.6 Приказ итеративног извршавања функциjе дефинисане на сл. 6.13 кад
jоj се саопште изабрани аргументи.

i s a

- 0 [2 1 5 3 5 4] ← пре уласка у петљу


.
ић
0 2 [ 2 1 5 3 5 4]

ов


а.


1 3 [2 1 5 3 5 4]


ат

ан






2 [2 1 5 3 5 4]
Гњ

8

ж





итерациjе

др

3 11 [2 1 5 3 5 4]
петље
ан


 за

4 [2 1 5 3 5 4]

16

ил





су


5 [2 1 5 3 5 4 ]

20
М






а



6 излазак из петље

1.

ав
02

пр

- 20 [2 1 5 3 5 4] ← након изласка из петље


–2

а
20

20 ← повратна вредност
Св
20

а.
©

Пример 6.9. Дефинишимо функциjу13 коjа израчунава максимални еле-


иj

мент непразног низа целих броjева.


рз

Дефинициjа тражене функциjе приказана jе на сл. 6.14. У свакоj ите-


ве

рациjи петље издваjа се по jедан елемент низа, и упоређуjе с вредно-


шћу променљиве m, коjа чува максималну вредност претходно издвоjених
на

елемената. Променљива m декларисана jе пре петље, и инициjализована


д

вредношћу првог елемента низа, па се у петљи врши издваjање елемената


Ра

почевши од другог елемента14 низа. Ако jе вредност издвоjеног елемента


већа од максималне вредности претходно издвоjених елемената, промен-
љивоj m се додељуjе вредност издвоjеног елемента. Петља се извршава

13
Упоредите с примером 4.28 у 4. поглављу.
14
Пошто се издваjање елемената из низа врши од другог елемента, променљива i
инициjализована jе вредношћу 1, а не 0.
6.4 Итеративна обрада низова целих броjева 189

све док се не издвоjе сви елементи низа, а након изласка из петље, вред-
ност променљиве m прослеђуjе се наредбом return као повратна вредност
функциjе. Извршавање дате функциjе кад jоj се саопште изабрани аргу-
менти илустровано jе у табели 6.7.

1 i n t maks ( i n t a [ ] , i n t n ) {
2 int m = a [ 0 ] ;
3 f o r ( i n t i = 1 ; i < n ; i ++)
4 i f (m < a [ i ] )
5 m = a[ i ];
6 return m;
7 }

.
Слика 6.14 Функциjа коjа израчунава максимални броj непразног низа целих бро-
ић
jева.
ов

а.
ат

ан
Гњ

ж
Табела 6.7 Приказ итеративног извршавања функциjе дефинисане на сл. 6.14 кад

др
jоj се саопште изабрани аргументи.
ан

i m a
за
ил

су
- 2 [ 2 1 5 3 5 4] ← пре уласка у петљу
М

1 2 [2 1 5 3 5 4]

1.

ав





02


2 5 [2 1 5 3 5 4]
пр






–2




3 5 [2 1 5 3 5 4]

а


итерациjе

20

Св

петље
4 5 [2 1 5 3 5 4]

20






а.


5 [2 1 5 3 5 4 ]

©

5



иj





6 излазак из петље

рз

- [2 1 5 3 5 4] ← након изласка из петље


ве

5
на

5 ← повратна вредност
д
Ра

Пример 6.10. Дефинишимо функциjу коjа израчунава броj jављања мак-


сималног елемента у непразном низу целих броjева.
Разлика у поставци овог примера у односу на поставку примера 6.9 jе
та што повратна вредност функциjе треба да буде jеднака броjу jављања
190 6 Итеративни процеси у императивном програмирању

максималног елемента у низу броjева, a не самом максималном елемен-


ту. Међутим, процес израчунавања броjа jављања максималног елемента
укључуjе израчунавање максималног елемента. Због тога се оваj проблем
може решити проширивањем изворног ко̂да датог на сл. 6.14. Решење jе
приказано на сл. 6.15. У постоjећи ко̂д уведена jе додатна променљива
broj, коjа се:
• увећава за 1 сваки пут кад jе издвоjени елемент jеднак текућоj макси-
малноj вредности сачуваноj у променљивоj m,
• реинициjализуjе вредношћу 1 сваки пут кад се вредност променљиве
m промени (тj., кад се промени текућа максимална вредност).

1 i n t broj_maksimalnih ( i n t a [ ] , i n t n ) {
.
ић
2 int m = a [ 0 ] ;
3 int b r o j = 1 ;
ов
4 f o r ( i n t i = 1 ; i < n ; i ++)

а.
5 i f (m == a [ i ] )
ат

ан
6 b r o j ++;
Гњ

7 e l s e i f (m < a [ i ] ) {

ж
8 m = a[ i ];

др
9 broj = 1;
ан

10 } за
11 return b r o j ;
ил

12 }
су
М

Слика 6.15 Функциjа коjа израчунава броj jављања максималног броjа у непразном
1.

ав

низу целих броjева.


02

пр
–2

У овом примеру ћемо се осврнути и на питање временске сложено-


а
20

Св

сти алгоритма. Треба приметити да итеративни процес имплементиран


изворним ко̂дом приказаним на сл. 6.15 захтева само jедан пролазак кроз
20

низ. Временску сложеност овог алгоритма можемо приближно проценити


а.
©

одређивањем броjа приступа низу a током извршавања функциjе — низу


иj

a приступа се n пута, где n представља броj елемената у низу (тj., сваком


рз

елементу низа приступа се по jеданпут). Оваква временска сложеност


ве

назива се линеарном.
Друго решење овог проблема, приказано на сл. 6.16, jе интуитивниjе,
на

али захтева два проласка кроз низ — у првом проласку се одређуjе мак-
д

симални елемент низа, и његова вредност се додељуjе променљивоj m, а


Ра

у другом проласку се израчунава броj jављања максималног елемента у


низу. Током извршавања ове функциjе, низу a се приступа 2n пута (тj.,
сваком елементу низа приступа се по два пута), а временска сложеност
овог алгоритма такође jе линеарна.
Коначно, у трећем решењу овог проблема, приказаном на сл. 6.17,
вредност максималног елемента низа израчунава се у свакоj итерациjи
петље, због чега jе ово решење неефикасно. Током извршавања функциjе,
6.4 Итеративна обрада низова целих броjева 191

1 i n t broj_maksimalnih ( i n t a [ ] , i n t n ) {
2 i n t m = maks ( a , n ) ;
3 int b r o j = 0 ;
4 f o r ( i n t i = 0 ; i < n ; i ++)
5 i f (m == a [ i ] )
6 b r o j ++;
7 return b r o j ;
8 }

Слика 6.16 Друга функциjа коjа израчунава броj jављања максималног броjа у не-
празном низу целих броjева.

низу a приступа се n(n + 1) пута (тj., сваком елементу низа приступа се


по n + 1 пута), a њена временска сложеност jе квадратна.
.
ић
Посматрано с аспекта исправности, сва три решења генеришу тачне
ов
резултате. Међутим, у односу на временску сложеност, прво решење jе

а.
оптимално.
ат

ан
Гњ

ж
1 i n t broj_maksimalnih ( i n t a [ ] , i n t n ) {

др
2 int b r o j = 0 ;
ан

3 f o r ( i n t i = 0 ; i < n ; i ++)
за
4 i f (m == maks ( a , n ) )
ил

5 b r o j ++;
су
М

6 return b r o j ;
7 }
а
1.

ав
02

пр

Слика 6.17 Трећа функциjа, квадратне временске сложености, коjа израчунава броj
–2

jављања максималног броjа у непразном низу целих броjева.


а
20

Св
20

Пример 6.11. Дефинишимо функциjу15 коjа обрће редослед елемената у


а.
©

непразном низу реалних броjева.


иj

Решење овог проблема приказано jе на сл. 6.18. У првоj итерациjи пе-


рз

тље врши се замена вредности првог и последњег елемента низа, у другоj


ве

итерациjи врши се замена вредности другог и претпоследњег елемента


низа, итд. За дати низ капацитета n потребно jе извршити b n2 c итерациjа
на

петље, због чега jе променљива i инициjализована вредношћу 0, а услов


д

за излазак из петље гласи16 i < n2 . У свакоj итерациjи петље врши се за-


Ра

мена вредности елеменaта a[i] и a[n − 1 − i]. Ако низ a садржи непарни
броj елемената, централни елемент низа остаjе непромењен, и ниjе пред-

15
Упоредите са сложениjим примером 4.19 у 4. поглављу.
16
Кад би услов за излазак из петље (грешком) гласио i < n, редослед елемената у
низу a био би обрнут два пута, тj., резултуjуће стање низа након изласка из петље
било би идентично почетном стању.
192 6 Итеративни процеси у императивном програмирању

мет обраде у телу петље. Извршавање дате функциjе кад jоj се саопште
изабрани аргументи илустровано jе у табели 6.8.

1 void o b r n i _ r e d o s l e d _ n i z a ( double a [ ] , i n t n ) {
2 f o r ( i n t i = 0 ; i < n / 2 ; i ++) {
3 double p = a [ i ] ;
4 a[ i ] = a[n − 1 − i ];
5 a[n − 1 − i ] = p;
6 }
7 }

Слика 6.18 Функциjа коjа обрће редослед елемената у непразном низу реалних бро-
jева.

.
ић
ов

а.
ат

Табела 6.8 Приказ итеративног извршавања функциjе дефинисане на сл. 6.18 кад

ан
jоj се саопште изабрани аргументи. У свакоj итерациjи, елемент a[i] означен jе сивом
Гњ

ж
боjом, а елемент a[n − 1 − i] црним оквиром.

др
i a
ан

за
- [1 2 3 4 5 6 7] ← низ пре уласка у петљу
ил

су

0 [ 7 23456 1 ]
М




а



1.


ав

1 [7 6 3 4 5 2 1]


итерациjе

02

петље
пр

2 [7 6 5 4 3 2 1]



–2





а

3 излазак из петље

20

Св

- [7 6 5 4 3 2 1] ← низ након изласка из петље


20

а.
©

иj

За разлику од претходних примера у овоj секциjи, ова функциjа не


рз

генерише директни резултат (због чега jе тип података њене повратне


ве

вредности декларисан као void), већ бочни ефекат коjи се рефлектуjе


кроз промену вредности елемената улазног низа. Пошто се саопштавање
на

низа као улазног аргумента функциjе врши тзв. преносом по референци


д

(в. секциjу 5.8 у 5. поглављу), промене извршене у телу функциjе над


Ра

елементима низа остаjу актуелне и након извршења функциjе.


Да би се замениле вредности елеменaта a[i] и a[n − 1 − i], у телу петље
декларисана jе помоћна променљива p:
double p = a [ i ] ;
a[ i ] = a[n − 1 − i ];
a[n − 1 − i ] = p;
6.4 Итеративна обрада низова целих броjева 193

Слично као у примеру 6.7, замена вредности могла се реализовати без


декларисања додатне променљиве, представљањем тела петље следећом
секвенцом наредби:
a[ i ] = a[ i ] + a[n − 1 − i ];
a[n − 1 − i ] = a[ i ] − a[n − 1 − i ];
a[ i ] = a[ i ] − a[n − 1 − i ];
а читаоцу се оставља да провери ову тврдњу, не занемаруjући чињеницу
да непотребно усложњавање ко̂да не спада у добру праксу.

Пример 6.12. Дефинишимо функциjу коjа проверава да ли jе непразни


низ целих броjева „палиндром“, тj., да ли jе редослед вредности елеме-
ната низа слева надесно идентичан редоследу вредности елемената низа
сдесна налево.
.
ић
Оваj проблем представља вариjанту проблема представљеног у при-
меру 6.11, а његово решење приказано jе на сл. 6.19. У првоj итерациjи
ов

а.
петље пореде се вредности првог и последњег елемента низа, у другоj
ат

ан
итерациjи пореде се вредности другог и претпоследњег елемента низа,
Гњ

итд. Из петље се излази на jедан од два начина:

ж
др
• кад се први пут издвоjи пар елемената чиjе су вредности различите,
ан

што значи да улазни низ ниjе „палиндром“ — извршавање функциjа се


за
одмах прекида, без даљег издваjања елемената из низа, а као повратна
ил

су

вредност прослеђуjе се 0,
М

• кад вредност променљиве i постане jеднака b n2 c, што значи да су вред-


а

ности елемената свих поjединачно издвоjених парова jеднаке, тj., ула-


1.

ав

зни низ jе „палиндром“, а као повратна вредност прослеђуjе се 1.


02

пр
–2

а
20

Св

1 int palindrom ( int a [ ] , int n ) {


20

2 f o r ( i n t i = 0 ; i < n / 2 ; i ++) {
3 i f ( a [ i ] != a [ n − 1 − i ] )
а.
©

4 return 0 ;
иj

5 }
рз

6 return 1 ;
7 }
ве
на

Слика 6.19 Функциjа коjа проверава да ли jе непразни низ целих броjева „палин-
дром“.
д
Ра

Пример 6.13. Дефинишимо функциjу коjа израчунава броj различитих


елемената у датом непразном низу целих броjева.
Итеративни процес израчунавања броjа различитих елемената у датом
непразном низу може се описати на следећи начин. Елементи се редом
издваjаjу из низа, и за сваки издвоjени елемент се проверава да ли jе
194 6 Итеративни процеси у императивном програмирању

jеднак неком од елемената коjи му претходе. Ако се вредност издвоjеног


елемента ниjе претходно jављала у низу, вредност променљиве коjа чува
броj различитих елемената у низу увећава се за jедан.

1 int b r o j _ r a z l i c i t i h ( int a [ ] , int n ) {


2 int b r o j = 1 ;
3 f o r ( i n t i = 1 ; i < n ; i ++) {
4 int j = 0 ;
5 f o r ( j = 0 ; j < i ; j ++)
6 i f ( a [ i ] == a [ j ] )
7 break ;
8 i f ( i == j )
9 b r o j ++;
10 }
11 return b r o j ;
.
ић
12 }
ов

а.
ат

Слика 6.20 Функциjа коjа израчунава броj различитих елемената у датом непразном

ан
низу целих броjева.
Гњ

ж
др
За имплементирање овог итеративног процеса примењене су две пе-
ан

за
тље, при чему jе jедна петља угнежђена у другоj (в. сл. 6.20). У спољноj
ил

петљи издваjаjу се редом елементи низа a, почевши од другог елемента


су

низа, и закључно с последњим елементом низа. За сваку текућу вредност


М

променљиве i, у унутрашњоj петљи се променљивоj j редом додељуjу


а
1.

ав

вредности из секвенце целих броjева 0, 1, . . . , i − 1, што омогућава поре-


02

ђење елемента a[i] с елементима a[0], a[1], . . . , a[i − 1], коjи му претходе у
пр

низу. Из унутрашње петље се излази на jедан од два начина:


–2

а
20

• први пут кад се наиђе на елемент коjи jе jеднак елементу a[i], извр-
Св

шавање унутрашње петље се прекида позивањем наредбе break, без


20

обзира на испуњеност услова петље,


а.
©

• кад вредност променљиве j постане jеднака вредности променљиве i,


иj

тj., кад услов петље ниjе испуњен.


рз

Променљива j декларисана jе пре унутрашње петље, па њен лексички оп-


ве

сег обухвата део изворног ко̂да до краjа тела спољне петље. Ако jе вред-
на

ност променљиве j након изласка из унутрашње петље jеднака вредности


променљиве i, то индикуjе да ниjедан од елемената a[0], a[1], . . . , a[i −1] ни-
д

jе jеднак елементу a[i], па се вредност променљиве broj увећава за 1.


Ра

Након изласка из спољне петље, вредност променљиве broj jеднака jе


броjу различитих елемената у низу a. Извршавање дате функциjе кад jоj
се саопште изабрани аргументи илустровано jе у табели 6.9.

Пример 6.14. Дефинишимо функциjу коjа уређуjе дати низ целих броjева
монотоно неопадаjуће.
6.4 Итеративна обрада низова целих броjева 195

Табела 6.9 Приказ итеративног извршавања функциjе дефинисане на сл. 6.20 кад
jоj се саопште изабрани аргументи. У свакоj итерациjи, елемент a[i] означен jе сивом
боjом, а елемент a[ j] црним оквиром.

broj i j a

1 - - [1 5 3 5 1] ← пре уласка у петље

1 0 [ 1 5 3 5 1] итерациjе 
) 
унутрашње 


петље

2 1 1 излазак из унутрашње петље








2 0 [ 1 5 3 5 1]
 

 

итерациjе

 



2 1 [1 5 3 5 1] унутрашње 



петље

 

 
2 2 излазак из унутрашње петље
.

3

ић 


итерациjе


3 0 [ 1 5 3 5 1] спољне
ов

а.

итерациjе петље

 
ат


3 1 [1 5 3 5 1]

ан
унутрашње 



петље
 
Гњ

 

ж
 
излазак из унутрашње петље

3


др




4 0 [ 1 535 1]
 
итерациjе 
ан


за 

унутрашње 


ил

3 излазак из унутрашње петље



петље
 

су



М


5 - излазак из спољне петље



а
1.

ав

3 - - [1 5 3 5 1] ← након изласка из петљи


02

пр
–2

3 ← повратна вредност
а
20

Св
20

Овде ћемо представити алгоритам за уређење низа заснован на тзв.


а.
©

методи избора наjмањег елемента. Временска сложеност овог алгоритма


иj

већа jе од временске сложености алгоритма за тзв. брзо уређење низа


рз

представљеног у 4. поглављу (в. пример 4.26), што значи да приказано


ве

решење ниjе оптимално. Међутим, овде га разматрамо, jер представља


jедан од концептуално наjjедноставниjих итеративних процеса уређења
на

низова.
д

Основна идеjа овог алгоритма може се описати на следећи начин. Прво


Ра

се наjмањи елемент низа премести на прво место низа, потом се наjмањи


елемент преосталог дела низа премести на друго место низа, итд., све
док се не уреде и последња два елемента низа. Дефинициjа функциjе
коjа имплементира оваj итеративни процес дата jе на сл. 6.21.
За имплементирање овог алгоритма примењене су две петље, при чему
jе jедна петља угнежђена у другоj. У спољноj петљи издваjаjу се редом
елементи низа a, почевши од првог елемента низа, и закључно с претпо-
196 6 Итеративни процеси у императивном програмирању

1 void u r e d i ( i n t a [ ] , i n t n ) {
2 f o r ( i n t i = 0 ; i < n − 1 ; i ++)
3 f o r ( i n t j = i + 1 ; j < n ; j ++)
4 if (a [ i ] > a [ j ]) {
5 int p = a [ i ] ;
6 a[ i ] = a[ j ];
7 a[ j ] = p;
8 }
9 }

Слика 6.21 Функциjа коjа уређуjе дати низ целих броjева монотоно неопадаjуће.

следњим елементом низа. За сваку текућу вредност променљиве i, у уну-


трашњоj петљи се променљивоj j редом додељуjу вредности из секвенце
.
ић
целих броjева i + 1, i + 2, . . . , n − 1, што омогућава поређење елемента a[i] с
ов
елементима a[i + 1], a[i + 2], . . . , a[n − 1], коjи га следе у низу. Сваки пут кад

а.
се наиђе на елемент a[ j] коjи има мању вредност од елемента a[i], врши
ат

ан
се замена њихових вредности, чиме се постиже да након изласка из уну-
Гњ

ж
трашње петље вредност елемента a[i] представља минималну вредност

др
подниза a[i], a[i + 1], a[i + 2], . . . , a[n − 1].
ан

Након изласка из спољне петље, низ a jе уређен монотоно неопадаjу-


за
ће. Извршавање дате функциjе кад jоj се саопште изабрани аргументи
ил

илустровано jе у табели 6.10.


су
М

а
1.

ав
02

6.5 Итеративна обрада матрица целих броjева


пр
–2

У овоj секциjи размотрићемо групу примера коjи се односе на итера-


20

Св

тивну обраду матрица целих броjева.


20

а.
©

Пример 6.15. Дефинишимо функциjу коjа израчунава збир парних еле-


иj

мената дате матрице целих броjева.


рз

Дефинициjа тражене функциjе приказана jе на сл. 6.22. Дата функциjа


прихвата три аргумента:
ве

( int m, int n , int a [ ] [ n ] )


на

где су:
д
Ра

• m — броj врста у матрици a,


• n — броj колона у матрици a,
• a[ ][n] — матрица над коjом се врши обрада.
6.5 Итеративна обрада матрица целих броjева 197

Табела 6.10 Приказ итеративног извршавања функциjе дефинисане на сл. 6.21 кад
jоj се саопште изабрани аргументи. У свакоj итерациjи, елемент a[i] означен jе сивом
боjом, а елемент a[ j] црним оквиром.

i j a

- - [4 5 2 1 3] ← низ пре уласка у петље

0 1 [ 4 5 2 1 3]
 

 


 

 
0 2 [ 2 5 4 1 3]

 


 

итерациjе

 


унутрашње 

0 3 [ 1 54 2 3]


петље
 


 

 
0 4 [ 1 542 3 ]

 


 


 

 
0 5 излазак из унутрашње петље
.
ић  







1 2 [1 4 5 2 3]
ов
 

а.

 

 
ат

 

ан
 
1 3 [1 2 5 4 3] итерациjе 

 


итерациjе
унутрашње 

Гњ

ж
1 4 [1 2 5 4 3 ] петље спољне

др

петље

 

 

1 5 излазак из унутрашње петље
ан

 

за 




ил


2 3 [1 2 4 3]

5
 

су
 

итерациjе 
 
М

 
2 4 [1 2 3 5 4 ] унутрашње 


а


петље
 

1.

ав


 

2 5 излазак из унутрашње петље



02


пр




итерациjе 

3 4 [1 2 3 4 5 ]
)
–2



унутрашње 

а



20

3 5 излазак из унутрашње петље петље



Св






20


4 - излазак из спољне петље


а.
©

- - [1 2 3 4 5] ← низ након изласка из петљи


иj
рз
ве

Због везе17 између показивача и низова, матрица се, у општем случаjу,


на

може интерпретирати као показивач на низ 18 :


д
Ра

( int m, int n , int ( ∗ a ) [ n ] )

17
В. секциjу 5.7 у 5. поглављу.
18
То значи да се приликом саопштавања матрице као улазног аргумента функциjе вр-
ши тзв. пренос по референци, тj., промене извршене у телу функциjе над елементима
матрице остаjу актуелне и након извршења функциjе.
198 6 Итеративни процеси у императивном програмирању

па jе при декларисању матрице као улазног аргумента дозвољено — мада


не и обавезно — изоставити прву димензиjу (тj., броj врста m). Међутим,
димензиjе матрице мораjу бити наведене пре саме матрице у листи ула-
зних аргумената.

1 i n t z b i r _ m a t r i c e ( i n t m, i n t n , i n t a [ ] [ n ] ) {
2 int s = 0 ;
3 f o r ( i n t i = 0 ; i < m; i ++)
4 f o r ( i n t j = 0 ; j < n ; j ++)
5 i f ( a [ i ] [ j ] % 2 == 0 )
6 s = s + a[ i ][ j ];
7 return s ;
8 }

.
ић
Слика 6.22 Функциjа коjа израчунава збир парних елемената дате матрице целих
броjева.
ов

а.
ат

ан
Основна идеjа итеративног процеса израчунавања збира парних еле-
Гњ

ж
мената матрице може се описати на следећи начин. Издваjање елемената

др
из матрице врши се од првог елемента матрице ка последњем, и сваки из-
ан

двоjени парни елемент сабира се са збиром претходно издвоjених парних


за
ил

елемената. У решењу приказаном на сл. 6.22, за издваjање елемената из


су

матрице примењене су две петље. У спољноj петљи, променљива i доби-


М

jа редом вредности из опсега индекса додељених врстама матрице a. За


а

сваку текућу вредност променљиве i, у унутрашњоj петљи се променљи-


1.

ав

воj j редом додељуjу вредности из опсега индекса додељених колонама


02

пр

матрице a. Другим речима, елементи матрице издваjаjу се у редоследу у


–2

коjем су смештени у радноj мемориjи19 . Извршавање дате функциjе кад


а
20

jоj се саопште изабрани аргументи илустровано jе у табели 6.10.


Св

Описани итеративни процес могао jе бити имплементиран применом


20

само jедне петље, што jе приказано на сл. 6.23. Читаоцу се оставља да


а.
©

провери ову тврдњу.


иj
рз
ве

1 i n t z b i r _ m a t r i c e ( i n t m, i n t n , i n t a [ ] [ n ] ) {
2 int s = 0 ;
на

3 f o r ( i n t i = 0 ; i < m ∗ n ; i ++)
4 i f ( a [ i / n ] [ i % n ] % 2 == 0 )
д

5 s = s + a[ i / n][ i % n];
Ра

6 return s ;
7 }

Слика 6.23 Друга функциjа коjа израчунава збир парних елемената дате матрице
целих броjева.

19
В. секциjу 5.5 5. поглављу.
6.5 Итеративна обрада матрица целих броjева 199

Табела 6.11 Приказ итеративног извршавања функциjе дефинисане на сл. 6.22 кад
jоj се саопште изабрани аргументи. У свакоj итерациjи, елемент a[i][ j] означен jе сивом
боjом.

i j s

- - 0 ← пре уласка у петљу

итерациjе унутрашње петље





z }| { 


j=0 j=1 j=2 j=3




     

3
81 7 3 8 17 38 1 7 381 7

0



0 8  6 49 
1 2  6 4 92   64 9 2  649 2  



2 5 80 1 5 8 01 58 0 1 580 1 



3



итерациjе унутрашње петље

.
ић 

итерациjе


z }| {
j=0 j=1 j=2 j=3 спољне
ов
петље

а.

3 817 3 8 17 38 1 7 381 7
     

0 
ат

ан
1 20  6 4 9 2 6 4 9 2 6 4 9 2 6 4 9 2  

1 


Гњ

2 5 801 5 8 01 58 0 1 580 1

ж



3

др


итерациjе унутрашње петље



ан



z
j=0 j=1
}|
j=2
за
j=3
{ 



ил





су
3 817 3 8 17 38 1 7 381 7
     

0
М

2 1 28  6 4 9 2 6 4 9 2 6 4 9 2 6 4 9 2 
а

2 5 801 5 8 01 58 0 1 580 1
1.

ав

3
02

- - ← након изласка из петље


пр

28
–2

а
20

Св

28 ← повратна вредност
20

а.
©

иj

Пример 6.16. Дефинишимо функциjу коjа проверава да ли jе дата ква-


рз

дратна20 матрица целих броjева симетрична у односу на главну диjаго-


налу.
ве

Решење овог проблема приказано jе на сл. 6.24. Применом две међу-


на

собно угнежђене петље, из матрице се редом издваjаjу парови елемената


a[i][ j] и a[ j][i], чиjе су позициjе симетричне у односу на главну диjаго-
д

налу. Елемент a[i][ j] се налази изнад главне диjагонале ако и само ако
Ра

важи i < j. Због тога се у спољноj петљи променљивоj i додељуjу редом


вредности 0, 1, . . . , n − 2, а у унутрашњоj петљи се променљивоj j додељу-
jу вредности i + 1, i + 2, . . . , n − 1, тj., вредности веће од текуће вредности
променљиве i. За сваки пар вредности (i, j), у телу унутрашње петље се
пореде вредности елемента a[i][ j], коjи се налази изнад главне диjагонале,
20
Квадратна матрица jе матрица код коjе jе броj врста jеднак броjу колона.
200 6 Итеративни процеси у императивном програмирању

и „симетричног” елемента a[ j][i], коjи се налази испод главне диjагонале.


У петљама се не приступа елементима на главноj диjагонали, jер њихове
вредности нису од значаjа.
Из функциjе се излази на jедан од два начина:
• кад се први пут издвоjи пар елемената чиjе су вредности различите,
што значи да дата матрица ниjе симетрична — извршавање функциjе
се одмах прекида, без даљег издваjања елемената из матрице, а као
повратна вредност прослеђуjе се 0,
• кад вредност променљиве i постане jеднака n, што значи да су вред-
ности елемената свих поjединачно издвоjених парова jеднаке, тj., дата
матрица jе симетрична — непосредно након изласка из петље, као по-
вратна вредност функциjе прослеђуjе се 1.

.
ић
1 int s i m e t r i c n a ( int n , int a [ ] [ n ] ) {
ов

а.
2 f o r ( i n t i = 0 ; i < n − 1 ; i ++)
ат

ан
3 f o r ( i n t j = i + 1 ; j < n ; j ++)
4 i f ( a [ i ] [ j ] != a [ j ] [ i ] )
Гњ

ж
5 return 0 ;

др
6 return 1 ;
7 }
ан

за
ил

су
Слика 6.24 Функциjа коjа проверава да ли jе дата квадратна матрица целих броjева
М

симетрична у односу на главну диjагоналу.


а
1.

ав
02

Извршавање дате функциjе кад jоj се саопште изабрани аргументи


пр

илустровано jе у табели 6.12.


–2

а
20

Св
20

6.6 Итеративна обрада стрингова


а.
©

иj

Последња група примера односи се на итеративну обраду стринго-


рз

ва. У програмском jезику Ц, стринг jе низ симбола чиjи jе капацитет


ве

означен посредно, применом специjалног симбола ’\0’ као индикатора за


завршетак стринга21 . Због тога, приликом саопштавања стринга као ула-
на

зног аргумента функциjе не саопштава се додатни улазни аргумент чиjа


д

вредност одговара капацитету низа.


Ра

Пример 6.17. Дефинишимо функциjу коjа одређуjе броj симбола у датом


стрингу, не укључуjући специjални симбол ’\0’.
Размотрићемо два решења овог проблема. Прво решење, приказано
на сл. 6.25, карактеристично jе за итеративну обраду низова. Симболи се

21
В. секциjу 5.5.1 у 5. поглављу.
6.6 Итеративна обрада стрингова 201

Табела 6.12 Приказ итеративног извршавања функциjе дефинисане на сл. 6.24 кад
jоj се саопште изабрани аргументи. У свакоj итерациjи, елемент a[i][ j] означен jе сивом
боjом, а елемент a[ j][i] црним оквиром.

i j

итерациjе унутрашње петље





z }| { 

j=1 j=2 j=3






8 17 3 8 1 3 81 7
     
3 7 


8
8 4 9 2
1 4 9 2 8 49 2 

0
 

   
9 0 1  1 9 0 1 90 1 
2 1 1 


3 7 21 6

7 2 16 7 2 1 6






итерациjе унутрашње петље






z }| { 
.

j=2 j=3
ић 




   
3 8 1 7 3 8 1 7


итерациjе
ов


9 2 4 9 2

а.
8 4 8
1 2     спољне
ат

1 9 0 1 1 9 0 1

ан
3 петље


2 1 6

7 2 1 6 7


Гњ

ж



итерациjе

др


унутрашње


ан



петље

за




ил

z }| { 


j=3

су



М

  
3 8 1 7




а

8 4 9 2


2 3

1.

ав


1
  
1 9 0 

02



1
пр

7 2 6




4 - излазак из спољне петље
–2

а
20

Св

1 ← повратна вредност
20

а.
©

иj

редом издваjаjу из стринга, почевши од првог симбола, све док се не из-


рз

двоjи специjални симбол ’\0’. За сваки издвоjени симбол, осим терминал-


ве

ног симбола, вредност променљиве коjа чува броj претходно издвоjених


симбола увећава се за 1.
на

Променљива i, коjа чува броj издвоjених симбола, декларисана jе пре


петље, и њен лексички опсег обухвата део изворног ко̂да до краjа тела
д
Ра

функциjе. Након изласка из петље, вредност променљиве i jеднака jе


броjу симбола у датом стрингу, и прослеђуjе се као повратна вредност
функциjе. Треба приметити да jе тело петље празно.
Друго решење, приказано на сл. 6.26, заснива се на адресноj аритме-
тици. Ако показивач p садржи мемориjску адресу на коjоj jе смештен
неки члан низа, онда jе вредност p + 1 jеднака адреси наредног елемента
202 6 Итеративни процеси у императивном програмирању

1 i n t d u z i n a ( char ∗ s ) {
2 int i ;
3 f o r ( i = 0 ; s [ i ] != ’ \0 ’ ; i ++);
4 return i ;
5 }

Слика 6.25 Функциjа коjа одређуjе броj симбола у датом стрингу.

у низу, без обзира на тип података елемената у низу22 . У општем слу-


чаjу, увећавањем показивача p за 1, вредност адресе на коjу p показуjе
не увећава се за 1, већ за цели броj t, коjи представља броj мемориj-
ских локациjа потребних да се смести вредност типа података на коjу p
показуjе. Из тога следи да се увећавањем показивача p за цели броj i,
.
ић
вредност адресе на коjу p показуjе увећава за i · t.
На почетку тела функциjе приказане на сл. 6.26 декларисан jе помоћни
ов

а.
показивач s1 , и инициjализован вредношћу показивача s, тj., оба покази-
ат

ан
вача садрже адресу првог симбола стринга. У свакоj итерациjи петље,
вредност показивача s1 увећава се за 1, тj., показивачу s1 се додељуjе
Гњ

ж
адреса следећег елемента у низу, све док се не дође до краjа стринга. На-

др
кон изласка из петље, s1 садржи адресу специjалног симбола ’\0’, а броj
ан

за
симбола у стрингу израчунава се као разлика показивача s1 и s. Изврша-
ил

вање дате функциjе кад jоj се саопшти изабрани аргумент илустровано


су

jе на сл. 6.27.
М

а
1.

ав

1 i n t d u z i n a ( char ∗ s ) {
02

пр

2 char ∗ s 1 = s ;
–2

3 while ( ∗ s 1 != ’ \0 ’ )
а

4 s 1++;
20

Св

5 return s 1 − s ;
20

6 }
а.
©

иj

Слика 6.26 Друга функциjа коjа одређуjе броj симбола у датом стрингу.
рз
ве

Пример 6.18. Дефинишимо функциjу коjа лексикографски пореди два


на

стринга, и генерише:
д

• вредност 0, ако jе први стринг лексикографски jеднак другом стрингу,


Ра

• негативну вредност, ако jе први стринг лексикографски мањи од дру-


гог стринга,
• позитивну вредност, у супротном.
Решење овог проблема приказано jе на сл. 6.28. У свакоj итерациjи
петље издваjа се по jедан симбол из сваког од датих стрингова, у редо-
22
В. секциjу 5.7 у 5. поглављу.
6.6 Итеративна обрада стрингова 203

пре уласка итерациjе након изласка


у петљу петље из петље
z }| {z }| {z }| {
ниже адресе ниже адресе ниже адресе ниже адресе
⇑ ⇑ ⇑ ⇑

... ... ... ...


’p’ s, s1 ’p’ s ’p’ s ’p’ s
’a’ ’a’ s1 ’a’ ’a’
’r’ ’r’ ’r’ s1 ’r’
’\0’ ’\0’ ’\0’ ’\0’ s1
... ... ... ...

⇓ ⇓ ⇓ ⇓
више адресе више адресе више адресе више адресе
s1 − s

.
ић | {z }
3
повратна
ов

а.
вредност
ат

ан
Слика 6.27 Приказ итеративног извршавања функциjе дефинисане на сл. 6.26 кад
Гњ

ж
jоj се саопшти изабрани аргумент.

др
ан

следу у коjeм су наведени. Из петље се излази кад издвоjени симболи


за
ил

нису jеднаки, или кад се издвоjе сви симболи из бар jедног од датих
су

стрингова.
М

а
1.

ав
02

1 i n t u p o r e d i ( char ∗ s1 , char ∗ s 2 ) {
пр

2 while ( ( ∗ s 1 == ∗ s 2 ) && ( ∗ s 1 != ’ \0 ’ ) ) {
–2

3 s 1 ++;
а
20

4 s 2 ++;
Св

5 }
20

6 return ∗ s 1 − ∗ s 2 ;
а.

7 }
©

иj
рз

Слика 6.28 Функциjа коjа лексикографски пореди два стринга.


ве

По овом опису итеративног процеса, услов петље дефинише се као


на

конjункциjа три буловска подизраза:


д
Ра

( ( ∗ s 1 == ∗ s 2 ) && ( ∗ s 1 != ’ \0 ’ ) && ( ∗ s 2 != ’ \0 ’ ) )
Међутим, оваj услов се може концизниjе формулисати. Ако бар jедан од
прва два подизраза има нетачну вредност, услов петље ниjе задовољен,
без обзира на буловску вредност трећег подизраза. У супротном, ако прва
два подизраза имаjу тачне вредности, вредност трећег подизраза такође
204 6 Итеративни процеси у императивном програмирању

мора бити тачна. У оба случаjа, трећи подизраз jе сувишан, и може се


уклонити23 из услова петље:
( ( ∗ s 1 == ∗ s 2 ) && ( ∗ s 1 != ’ \0 ’ ) )
Резултат ове функциjе израчунава се као разлика симбола на коjе ре-
спективно показуjу s1 и s2 након изласка из петље. У програмском jезику
Ц, симболичке константе су, у ствари, цели броjеви, тj., свака симболич-
ка константа представљена jе целоброjним машинским ко̂дом, што значи
да се над симболима могу примењивати исте операциjе као и над целим
броjевима. Ако су симболи ∗s1 и ∗s2 jеднаки након изласка из петље, тj.,
ако важи:
( ( ∗ s 1 == ’ \0 ’ ) && ( ∗ s 2 == ’ \0 ’ ) )
њихова разлика jеднака jе 0, што индикуjе да су стрингови s1 и s2 лекси-
.
ић
кографски jеднаки. Ако симболи ∗s1 и ∗s2 нису jеднаки након изласка из
петље, то значи да стрингови s1 и s2 нису лексикографски jеднаки, а знак
ов

а.
разлике целоброjних вредности коjе представљаjу ове симболе индикуjе
ат

ан
лексикографски однос стрингова.
Гњ

ж
Треба уочити важну разлику у односу на претходни пример. У приме-

др
ру 6.17, повратна вредност функциjе одређена jе као разлика показивача,
ан

а у овом примеру као разлика симбола. за


ил

су
М

6.7 Закључне напомене


а
1.

ав
02

пр

Петље представљаjу примарни синтаксички инструмент за имплемен-


–2

тирање итеративних процеса у императивном програмирању. У овом по-


а

глављу размотрене су две изабране, функционално еквивалентне синтак-


20

Св

сичке структуре петље у програмском jезику Ц. Трећа функционално


20

еквивалентна синтаксичка структура петље у програмском jезику Ц ниjе


а.
©

посебно размотрена, jер представља синтаксички шећер, тj., не повећава


иj

експресивност jезика у односу на представљене синтаксичке структуре,


рз

нити уводи концептуално нове аспекте итеративних процеса у импера-


ве

тивном програмирању.
на

Библиографскe напоменe:
д
Ра

• Детаљни преглед синтаксичких структура петље у програмском


jезику Ц дат jе у поглављу „3. Control Flow” библиографског на-
вода [17].

23
Аналогно, из почетног услова петље се може уклонити други подизраз, уместо
трећег.
6.8 Задаци 205

• Саопштавање матрице као улазног аргумента функциjе размотре-


но jе у секциjи „11.3 Pointers and arrays” библиографског навода
[12].
• Адресна аритметика и итеративна обрада стрингова размотрене
су у секциjама „5.4 Address Arithmetic” и „5.5 Character Pointers
and Functions” библиографског навода [17].
• Израз синтаксички шећер, коjи означава проширење синтаксе
програмског jезика коjе не повећава експресивност jезика, уведен
jе у библиографском наводу [19].

.
ић
6.8 Задаци
ов

а.
Задатак 6.1. Претпоставите да jе n природни броj већи од 1. Дефини-
ат

ан
шите функциjу коjа одређуjе наjмањи нетривиjални делилац броjа n (тj.,
Гњ

ж
наjмањи делилац чиjа jе вредност већа од 1).

др
ан

Задатак 6.2. а) Дефинишите функциjу коjа одређуjе редно место по-


за
следњег jављања цифре c у ненегативном целом броjу n. Ако броj n не
ил

садржи цифру c, повратна вредност функциjе треба да буде jеднака 0.


су
М

б) Проширите решење из тачке а) овог задатка, тако да функциjа


а

генерише редно место првог jављања цифре c у броjу n.


1.

ав
02

Задатак 6.3. Дефинишите функциjу коjа проверава да ли jе дати при-


пр

родни броj „палиндром“.


–2

а
20

Св

Задатак 6.4. Дефинишите функциjу коjа израчунава збир свих пози-


20

тивних броjева садржаних у датом низу реалних броjева.


а.
©

Задатак 6.5. Дефинишите функциjу коjа циклично ротира непразни


иj

низ реалних броjева за jедно место улево.


рз
ве

Задатак 6.6. Дефинишите функциjу коjа прихвата два низа целих бро-
jева, и утврђуjе да ли за сваки елемент првог низа постоjи бар jедан
на

елемент исте вредности у другом низу.


д
Ра

Задатак 6.7. Дефинишите функциjу коjа проверава да ли jе дата ква-


дратна матрица симетрична у односу на споредну диjагоналу.

Задатак 6.8. Дефинишите функциjу коjа за дату квадратну матрицу


целих броjева израчунава разлику збира елемената на главноj диjагонали
и збира елемената изнад споредне диjагонале.
©
20
20
–2
02
Ра 1.
д М
на ил
ве ан
рз Гњ
иj ат
а.
Св ов
а ић
.
пр
ав
а
су
за
др
ж
ан
а.
Библиографиjа

.
ић
[1] Harold Abelson, Gerald Jay Sussman, Julie Sussman (1996) Structure and
Interpretation of Computer Programs, second edition, MIT Press, Cambridge,
ов

а.
Massachusetts, London, England.
ат

ан
[2] Robert J. Chassell (2009) An Introduction to Programming in Emacs Lisp, revised
third edition, GNU Press, Free Software Foundation, Inc.
Гњ

ж
[3] Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest, Clifford Stein (2009)

др
Introduction to Algorithms, third edition, Cambridge, Massachusetts: MIT Press.
[4] Paul Deitel, Harvey Deitel (2016) C: How to Program, eight edition, global edition,
ан

Pearson Education Limited.


за
ил

[5] Matthias Felleisen, Robert Bruce Findler, Matthew Flatt, Shriram Krishnamurthi
су

(2014) How to Design Programs, second edition, MIT Press.


М

[6] Matthew Flatt and PLT (2010) The Racket Reference, PLT-TR-2010-1, PLT Design
а

Inc (version 7.8, August 2020).


1.

ав

[7] Daniel P. Friedman, Matthias Felleisen (1995) The Seasoned Schemer, Second
02

Edition, The MIT Press.


пр

[8] Daniel P. Friedman, Mitchell Wand (2008) Essentials of Programming Languages,


–2

Third Edition, The MIT Press.


а
20

[9] Милан Гњатовић, Дарко Стефановић (2018) Изабране теме из безбедности и


Св

сигурности информационих система. Факутет техничких наука у Новом Саду.


20

[10] Paul Graham (1995) ANSI Common Lisp, Prentice Hall.


а.

[11] Paul Graham (1993) On Lisp, Prentice Hall.


©

[12] Jens Gustedt (2019) Modern C, second edition, Manning Publications.


иj

[13] Charles Antony Richard Hoare (1961) Algorithm 64: Quicksort. Communications of
рз

the ACM, 4(7), July 1961, 321.


[14] John Hughes (1990) Why Functional Programming Matters. In: D. Turner (ed.),
ве

Research Topics in Functional Programming, Addison-Wesley, pp. 17–42.


[15] IEEE (2019) IEEE Standard for Floating-Point Arithmetic, IEEE Std 754–2019
на

(Revision of IEEE 754-2008), pp.1–84.


д

[16] ISO/IEC JTC 1/SC 22 (2018) ISO/IEC 9899:2018 Information


Ра

technology — Programming languages — C, fourth edition,


https://www.iso.org/standard/74528.html.
[17] Brian W. Kernighan, Dennis M. Ritchie (1988) The C Programming Language,
second edition, Prentice-Hall, Englewood Cliffs, New Jersey.
[18] Donald Knuth (1973) The Art of Computer Programming Vols. I–III, Reading,
Massachusetts: Addison Wesley.
[19] Peter J. Landin (1964) The mechanical evaluation of expressions, The Computer
Journal, 6(4), pp. 308–320.
[20] John McCarthy (1978) History of LISP, ACM SIGPLAN Notices, 13(8).

207
208 БИБЛИОГРАФИJА

[21] John McCarthy, Paul W. Abrahams, Daniel J. Edwards, Timothy P. Hart, Michael
I. Levin (1962) LISP 1.5 Programmer’s Manual, The MIT Press.
[22] Peter Norvig (1992) Paradigms of Artificial Intelligence Programming: Case studies
in Common Lisp. San Francisco, Calif: Morgan Kaufmann Publishers.
[23] Alan J. Perlis (1982) Epigrams on Programming, SIGPLAN Notices, 17(9), pp. 7–13.
[24] Roland Pesch, Osier JM (2000) The GNU Binary Utilities, Version 2.9.1. iUniverse
https://ftp.gnu.org/old-gnu/Manuals/binutils-2.12/binutils.html.
[25] Dennis M. Ritchie (1993) The development of the C language, ACM SIGPLAN
Notices 28(3), pp. 201–208.
[26] Alex Shinn, John Cowan, and Arthur A. Gleckler (Eds.) et al. (2013)
Revised7 Report on the Algorithmic Language Scheme, R7RS Working Group 1,
https://small.r7rs.org/, accessed November 22, 2020.
[27] Michael Sperber, R. Kent Dybvig, Matthew Flatt, Anton Van Straaten, Robby
Findler, Jacob Matthews (2009). Revised6 Report on the Algorithmic Language
Scheme. Journal of Functional Programming, 19(S1), pp. 1–301.
[28] Richard M. Stallman, Roland Pesch, Stan Shebs (2011) Debugging with GDB: The
.
GNU Source-Level Debugger, V 7.3.1, Tenth Edition. Free Software Foundation, Inc.
ић
http://www.gnu.org/software/gdb/documentation/.
ов
[29] Richard M. Stallman et al. (2003) Using the GNU Compiler Collection. Free Software

а.
Foundation, Inc. https://gcc.gnu.org/onlinedocs/gcc-7.2.0/gcc.pdf.
ат

ан
[30] Michael Thorne (1991) Computer Organization and Assembly Language
Programming for IBM PCs and Compatibles (2nd ed.). The Benjamin/Cummings
Гњ

ж
Publishing Company, Inc.

др
[31] David S. Touretzky (1990) COMMON LISP: A Gentle Introduction to Symbolic
ан

Computation, The Benjamin/Cummings Publishing Company, Inc.


за
[32] Christian Queinnec (1996) Lisp in Small Pieces (K. Callaway, Trans.). Cambridge:
ил

Cambridge University Press.


су

[33] Joseph Weizenbaum (1976) Computer Power and Human Reason: From Judgment
М

to Calculation, W. H. Freeman & Co. New York, NY, USA.


а
1.

ав
02

пр
–2

а
20

Св
20

а.
©

иj
рз
ве
д на
Ра
Индекс поjмова

.
ић
ов
А декларисање показивача, 164, 165, 202

а.
адресна аритметика, 201, 205 декларисање променљиве, 148, 149,
ат

ан
152–154, 164, 165, 172, 177, 182,
185–188, 192–194, 201
Гњ

ж
безимене функциjе, 31, 53, 56, 57, 69, декларисање функциjе, 154, 170, 192

др
134, 135 десна асоциjативност, 150, 158
ан

бесконачност диграф, 23 за
негативна, 11, 12 дисjункциjа, 17, 145, 147, 148
ил

позитивна, 11, 12, 49, 136 екслузивна, 50, 107


су

блок, 172 дужина стринга, 23, 28, 200


М

бочни ефекат, 143, 154, 192


а

броjеви И
1.

ав

комплексни, 8–10, 13, 15, 16, 20, 144 именовани улазни аргумент, 66, 67,
02

69, 131, 132


пр

непрецизни, 9–12, 20, 26, 65, 66


индекс, 23, 24, 112, 138, 159–162, 167,
–2

прецизни, 9–12, 20, 26


198
а

рационални, 8–10, 13, 16, 20, 21


20

инфиксна нотациjа, 3, 4, 6, 145


Св

реални, 8–14, 16, 20, 21, 144


цели, 8–10, 13–16, 20, 23, 144–146, итеративни процес, 71, 98–100, 108,
20

204 110–114, 116, 118, 119, 122–125,


а.
©

буловске вредности, 3, 16–18, 20, 22, 128, 129, 131, 175, 176, 180, 182,
иj

24, 27, 145, 147, 148, 203 184, 185, 187, 190, 193–195, 198,
203, 204
рз

итерациjа петље, 176, 179, 181–183,


В
ве

185–194, 196, 198, 200, 202


валидност улазних аргумената, 35,
36, 46, 69
на

К
временска сложеност, 190, 191, 195 конверзиjа, 13, 76, 151–153, 167
квадратна, 191
д

експлицитна, 25, 26, 152, 153


Ра

линеарна, 190 имплицитна, 26, 152, 153, 184


конjункциjа, 17, 37, 38, 145, 147, 148,
Г 157, 203
глобалнo окружење, 33, 96 константа, 32, 144, 145, 151, 162, 168,
граф, 137 204

Д Л
декларисање низа, 159, 160, 163, 164, лексички опсег, 57–61, 63, 64, 96, 172,
168, 169, 174, 198 177, 182, 183, 194, 201

209
210 ИНДЕКС ПОJМОВА

лењо израчунавање, 148 165, 167, 168, 171, 172, 176, 177,
листа, 101, 103–125, 127–139 179, 180, 182, 183, 185–194, 196,
локално повезивање, 60, 64, 69, 97 198–201
паралелно, 60–62, 64, 69 глобалне, 31–33, 57–59
секценциjално, 60, 62–64, 69 локалне, 31, 57–64, 67, 97, 149,
171–173, 185
М прости броj, 93–97, 184
матрица, 137, 160, 161, 196–200, 205
Р
Н
рекурзивни процес, 71, 98–100, 108,
наводници, 22, 163
110, 111, 113, 114, 116, 119, 120,
неброj, 12
122–125, 127–129, 139, 175
негациjа, 17, 145, 147
репна рекурзиjа, 65, 71, 76–80, 83–86,
нетерминални чвор, 88
92–94, 97–100, 118
неутрални елемент, 80, 86, 177, 179,
референтнa транспарентност, 143
182
низ, 143, 145, 159–165, 167–169, 172,
.
ић
174, 184–197, 200–202, 205 С
сигмоидна функциjа, 63, 174
ов

а.
О симболи, 3, 22–24, 28, 29, 144, 145,
ат

област видљивости, 57, 96, 182 162, 200–204

ан
Оjлеров броj, 63, 174 специjални, 22, 23, 162–164, 169,
Гњ

ж
оквир стека, 67, 74–76, 78, 80, 81, 86, 200–202

др
88, 90, 93, 100, 171 синтаксички шећер, 181, 204, 205
скуп, 137, 176
ан

П
за
суфиксни оператор, 151
ил

петља, 99, 175–177, 179, 181–183,


су
185–196, 198–204 Т
М

подразумевана вредност улазног тело петље, 176, 177, 179, 182, 186,
а

аргумента, 23, 26, 27, 65–67, 69, 192–194, 199, 201


1.

ав

77, 80, 131, 132


тело функциjе, 35, 37–40, 44, 58, 59,
02

позивни стек, 67–69, 73–81, 85, 86, 88,


пр

76, 87, 95–97, 121, 136, 154–156,


90, 93, 98, 100, 149, 169, 171, 173
168–172, 179, 182, 185, 187, 192,
–2

показивач, 101–103, 143, 164, 165,


197, 201, 202
а

167–172, 187, 197, 201, 202, 204


20

Св

терминални чвор, 88
показивач на низ, 197
20

полунаводници, 22
а.

праг, 65, 66 У
©

празни стринг, 22–24, 28 уређени пар, 101–107, 114, 136, 138


иj

предикат, 20, 21, 25, 37, 46, 106, 107 услов петље, 176, 191, 194, 203, 204
рз

прекорачење бафера, 168, 173 условно извршавањe, 31, 40, 41,


пренос по вредности, 171, 172, 177 44–47, 49, 51, 52, 55, 121, 143,
ве

пренос по референци, 171, 187, 192, 154–158, 179, 185


197 вишеструко гранање, 47–51
на

префиксна нотациjа, 3, 4, 6, 7, 12, 18,


д

33, 35 Ф
Ра

префиксни оператор, 151 факториjел, 86, 181, 182, 184


приордер-обилазак, 88 Фибоначиjев низ, 87, 88, 92, 93,
променљиве, 31–34, 38, 58–60, 64, 65, 184–186
69, 98, 143, 148–153, 158, 164, функциjе вишег реда, 31, 53, 69, 125

You might also like