Обучили смо вас за рад са променљивама и функцијама, а сада улазимо у мутне воде Скимових спискова.
Пре него што почнемо да причамо више о списковима, неопходно је да знате разлику између атомских вредности и спискова.
Већ сте видели атомске вредности када смо иницијализовали променљиве у претходној лекцији. Атомска вредност је појединачна вредност. Тако, на пример, можемо доделити променљивој „x“ појединачну вредност 8 у следећој наредби:
(let* ( (x 8) ) x)
(Додали смо израз x на крају да бисмо исписали вредност додељену променљивој x — обично то нећете морати да радите. Приметите како let* ради баш као функција: вредност последње наредбе је враћена вредност.)
Променљива се такође може односити на списак вредности, уместо на појединачну вредност. Да бисмо променљивој x доделили списак вредности 1, 3, 5, куцали бисмо:
(let* ( (x '(1 3 5))) x)
Пробајте да унесете обе наредбе у Скрипт-фу конзолу и приметићете како она одговара. Када унесете прву наредбу, она једноставно одговара резултатом:
8
Међутим, када унесете другу наредбу, она одговара следећим резултатом:
(1 3 5)
Када одговори вредношћу 8, она вас обавештава да x садржи атомску вредност 8. Међутим, када одговори са (1 3 5), она вас обавештава да x не садржи појединачну вредност, већ списак вредности. Приметите да нема запета у нашој декларацији или додели списка, као ни у одштампаном резултату.
Синтакса за дефинисање списка је:
'(a b c)
где су a, b и c литерали. Користимо апостроф (') да означимо да је оно што следи унутар заграда списак дословних вредности, а не функција или израз.
Празан списак се може дефинисати на следећи начин:
'()
или једноставно:
()
Спискови могу садржати атомске вредности, као и друге спискове:
(let*
(
(x
'("GIMP" (1 2 3) ("is" ("great" () ) ) )
)
)
x
)
Приметите да након првог апострофа више не морате да користите апостроф приликом дефинисања унутрашњих спискова. Слободно копирајте овај израз у Скрипт-Фу конзолу и погледајте шта враћа.
Требало би да приметите да враћени резултат није списак појединачних, атомских вредности; већ је то списак литерала ("GIMP"), списак (1 2 3), итд.
Корисно је размишљати о списковима као о нечему што се састоји од „главе“ („head“) и „репа“ („tail“). Глава је први елемент списка, а реп је остатак списка. Видећете зашто је ово важно када будемо разговарали о томе како се додаје у спискове и како се приступа елементима у списку.
Једна од чешћих функција са којима ћете се сусрести је функција „cons“. Она узима вредност и поставља је на свој други аргумент, списак. Из претходног одељка, предложио сам вам да размишљате о списку као о нечему што се састоји од елемента (главе) и остатка списка (репа). Управо тако „cons“ функционише — додаје елемент на главу списка. Тако бисте могли да направите списак на следећи начин:
(cons 1 '(2 3 4) )
Резултат је списак (1 2 3 4).
Такође бисте могли да направите списак са једним елементом:
(cons 1 () )
Можете користити претходно декларисане променљиве уместо било којих литерала, као што бисте и очекивали.
Да бисте дефинисали списак састављен од литерала или претходно декларисаних променљивих, користите функцију list:
(list 5 4 3 a b c)
Ово ће саставити и вратити списак који садржи вредности променљивих a, b и c. На пример:
(let* (
(a 1)
(b 2)
(c 3)
)
(list 5 4 3 a b c)
)
Овај код прави списак (5 4 3 1 2 3).
За приступање вредностима у списку, користите функције car и cdr, које враћају први елемент списка, односно остатак списка. Ове функције разлажу списак на структуру глава::реп коју сам раније поменуо.
car враћа први елемент списка (главу списка). Списак не сме бити празан (non-null). Тако следеће враћа први елемент списка:
(car '("first" 2 "third"))
који је:
"first"
cdr враћа остатак списка након првог елемента (реп списка). Ако у списку постоји само један елемент, враћа празан списак.
(cdr '("first" 2 "third"))
враћа:
(2 "third")
док следеће:
(cdr '("one and only"))
враћа:
()
У реду, сјајно, можемо да добијемо први елемент листе, као и остатак листе, али како да приступимо другом, трећем или осталим елементима листе? Постоји неколико „погодних“ функција за приступање, на пример, глави главе репа листе (caadr), репу репа листе (cddr), итд.
Основно правило именовања је једноставно: слова „a“ и „d“ представљају главе и репове листи, тако да
(car (cdr (car x) ) )
може бити записано као:
(cadar x)
Да бисте мало вежбали са функцијама за приступање листи, покушајте да укуцате следеће (осим што све иде у један ред ако користите конзолу); користите различите варијације функција car и cdr за приступање различитим елементима листе:
(let* (
(x '( (1 2 (3 4 5) 6) 7 8 (9 10) )
)
)
; овде поставите ваш car/cdr код
)
Покушајте да приступите броју 3 у листи користећи само два позива функције. Ако то успете, на добром сте путу да постанете мајстор Скрипт-фуа!
|
Примедба |
|---|---|
|
У Шеми (Scheme), тачка-зарез ( |