Руби (програмски језик)

Из Википедије, слободне енциклопедије
Ed NL icon.png
Овај чланак је део пројекта семинарских радова на Математичком факултету у Београду.
Датум уноса: октобар—децембар 2017.
Википедијанци: Ова група студената ће уређивати у ГИП-у и молимо вас да не пребацујете овај чланак у друге именске просторе Википедије.
Позивамо вас да помогнете студентима при уређивању и допринесете да њихови уноси буду што квалитетнији.
Руби (програмски језик)
Ruby logo.svg
Појавио се 1995
Аутор(и) Јукихиро Мацумото
Актуелна верзија 2.2.1
Типови променљивих динамички
Имплементације Ruby MRI, YARV, JRuby, Rubinius, IronRuby, MacRuby, HotRuby
Утицаји Перл, Пајтон, Lisp, C++, Smalltalk, Dylan, CLU
Оперативни системи сви значајнији
Лиценца Руби Лиценца
Веб-сајт www.ruby-lang.org
Документација Документација

Руби (енгл. Ruby) је објектно оријентисани програмски језик. У себи комбинује синтаксу инспирисану језицима Перл и Ада, са објектно оријентисаним особинама налик језику Smalltalk (Smalltalk), а дели и неке особине са језицима Пајтон, Lisp, Dylan и CLU. Руби је једнопролазни интерпретирани језик. Његова главна имплементација је слободни софтвер под лиценцом отвореног кода.

Јукихиро „Мац“ Мацумото (Yukihiro Matsumoto) је са развојем овог језика почео у фебруару 1993. године. Први пут је објављен 1995. године, а тренутно је актуелна стабилна верзија 1.9.3-p0 која се може преузети са званичне стране језика. По многим програмерима, Руби слиједи принцип „најмањег изненађења“, чиме мисле да је тај језик ослобођен свих замки и контрадикторности познатих из других језика. Име „руби“ потиче од енглеске ријечи за „рубин“ (енгл. Ruby) што је само алузија на „перл“ (енглески „бисер").

Руби је дуго времена био чисто јапанска појава, гдје је постигао велику популарност, отприлике једнаку као Перл или Пајтон. Документација је постојала само на јапанском. „Мац“ је тек крајем миленијума кренуо са активностима популаризације тог програмског језика и изван Јапана. Веома брзо је прихваћен и убрзо затим су објављени многобројни чланци у стручним часописима као и документација на другим језицима.

Садржај

Рани концепти[уреди]

“Разговарао сам са колегом о могућностима објектно-оријентисаног скрипт језика. Знао сам Perl, али ми се није стварно свиђао, јер је био налик на toy језике. Објектно-оријенстисани језици су деловали врло обећавајуће. Тада сам научио Python. Али ми се није свиђао, јер нисам мислио да је прави објектно-оријентисани језик: имао је само неке карактеристике ОО као додатке. Као залуђеник програмским језицима и фан ОО већ 15 година, заиста сам желео истински објектно оријентисан, једноставан за употребу програмски језик. Тражио сам, али нисам могао пронаћи један. Зато сам одлучио да га направим.”

Мацумото описује да је дизајн Рубиja једноставан као језгро језика Lisp, са системом објеката налик на Smalltalk и практичне корисности као Perl.

Прво издање[уреди]

Прво јавно издање програмског језика Руби[1] 0.95 објављено је на јапанске newsgroup 21. децембра 1995.године. Након тога, још три верзије програмског језика су објављење у два дана. Након објављивања Руби 0.95 , неколико стабилних верзија језика су објављење у наредним годинама:

  • Руби 1.0 децембар 25, 1996
  • Руби 1.2: децембар 1998
  • Руби 1,4: август 1999
  • Руби 1.6: септембар 2000
Године 1997,  објављен је први чланак о језику Руби на интернету. Исте године, Матсумото је ангажован од стране  netlab.jp да ради као full-time developer у програмском језику Руби.
Године 1998. године, покренута је апликација Ruby Application Archive , заједно са једноставном страницом на енглеском језику за Ruby. 
Године 1999,  Мацумото и Кеију Исхитсука су написали прву књигу(The Object-Oriented Scripting Language Ruby, октобар 1999.) о овом програмском језику, за који је порасло интересовање и ван Јапана, То је праћено објављивањем још 20 књига о овом језику у Јапану, ране 2000.године.
До 2000. године, Ruby је постао популарнији него Python у Јапану.  У септембру 2000. године, прва књига на енглеском језику, Programming Ruby[2] је штампана, док је несто касније пуштена у слободну продају, што је продубило усвајање овог програмског језика и у другим земљама. 

Најновије верзије програмског језика Руби:

  • Руби 2.5.0[3], октобар 2017.
  • Руби 2.4.2[4], септембар 2017.
  • Руби 2.3.5[5], септембар 2017.

Филозофија програмског језика Ruby[6][уреди]

Мацумото је рекао да је Руби дизајниран за продуктивност програмера и забаву, на начелима доброг дизајна корисничког интерфејса. На Google Tech Talk-u, 2008.године Мацумото даље наводи: “Надам се да ће Ruby помоћи сваком програмеру у свету да би буде продуктивнији, и да ужива у програмирању, и да буде срећнији. То је примарна сврха језика Руби. “ Он наглашава да дизајн система треба да пре задовољи потребе човека, а не рачунара.

“Често људи, посебно програмери, фокусирају се на машине. Они мисле: “Радећи ово машина ће радити  брже, успешније...”  Они се фокусирају на машине. Али, у ствари, морамо да се фокусирамо на људе, на начин програмирања  или ради управљења апликацијама. Ми смо господари. Они су робови.”

Језик Ruby треба да поштује принцип ПОЛА, што значи да треба да се понаша на такав начин да минимизира забуне за искусне кориснике. Мацумото је рекао да је његов примарни циљ дизајна је био да се направи језик који он сам ужива користи, смањујући рад програмера и могућу забуну. Он је рекао да није применио принцип ПОЛА у дизајну језика, али је без обзира на то фраза у блиској асоцијацији са језиком Ruby. Фраза је и сама била извор изненађења, посто су многи почетни корисници могли да помисле да језик Руби опонаша понашање других језика. У мају 2005.године дискусијом на newsgroup.comp.lang.ruby, Мацумото покушао да дистанцира Руби од ПОЛА принципа, објашњавајући да посто је било који избор дизајна изненађујући за некога, он користи лични стандард у процени изненађења. Ако смо доследни у личном стандарду, биће мање изненађења за упознате са стандардом. Мацумото је то објаснио на следећи наћин: "Сви имају сопствену позадину. Неки програмирају у Python-у, неки у Perl-y, И они могу бити изненађени различитим аспектима језика. Онда они дођу код мене И кажу: “Био сам изненађен овом карактеристиком језика, тако да Руби нарушава принцип најмањег изненађења”. Чекај. Чекај. Принцип најмањег изненађења није само за тебе. Односи се на принцип мог најмањег изненађења и односи се на принцип најмањег изненађења након што научиш Руби веома добро. На пример, ја сам био C++ програмер пре него сто сам започео дизајнирање језика Руби. Програмирао сам искључиво у C++ две или три године. И после две године C++ ме И даље изненађује."

Особине[уреди]

  • Једноставна и читљива синтакса
  • „Чисто“ објектно оријентисани језик (слично Smalltalkу)
    • „Све“ је објект
    • Наслеђивање од модула, умјесто вишеструког наслеђивања
    • Уникатне методе (Singleton)
    • Динамична промјена имена и надоградња класа приликом извршења програма
    • Итератори
    • Преписивање оператора
    • Интроспекција (Reflection)
  • Нетипизоване варијабле
  • Обрада изузетака
  • аутоматско ослобађање непотребно заузете меморије (garbage collection)
  • подршка Перлових регуларних израза (још непотпуна)
  • подршка на више оперативних система
  • јединствен интерфејс за приступ базама података
  • аутоматска документација (слично javadoc)
  • могућност и функционалног и процедуралног програмирања
  • либерална лиценца (ГНУ или по жељи)

Руби је потпуно објектно оријентисан. Све променљиве су објекти, што важи, за разлику од Џаве (java), и за примитивне типове.

Опште карактеристике програмског језика Руби[уреди]

Руби је интерпретирани програмски језик, што значи да се изворни кôд преводи у кôд разумљив рачунару приликом сваког извршавања програма. Очити је недостатак интерпретираних програмских језика то да су спорији него компајлирани програмски језици као што је на пример C. Предност је њихова већа флексибилност и краће време израде програма. Руби је потпуно објектно- оријентисан програмски језик, што значи да се програмски проблеми решавају дефинисањем класа, а из класа настају појединачни објекти. Једна је од предности објектно-оријентисаног приступа то да он олакшава рад на великим пројектима јер је задатак могуће поделити на више програмера, од којих сваки може засебно радити на једној класи или на више њих. На почетку рада се дефинишу поруке које се могу слати одређеном објекту, а након тога програмери имају слободу писати и мењати кôд унутар класе под условом да поруке остају непромењене. Објектно-оријентисана метода решавања проблема врло је учинковита јер рашчлањује проблеме на природан начин сличан ономе који се употребљава у решавању проблема у свакодневном животу. Руби припада отвореном коду будући да је објављен под лиценцом ГПЛ[7]. Временом је објављено више алтернативних интерпретера програмског језика Руби. Најпознатији је JRuby[8] који је написан у програмском језику Java.

Предности и недостаци[уреди]

За Руби се каже да има природну синтаксу. Наиме, синтакса програмског језика Руби не садржи непотребне знакове и стога кôд написан у програмском језику Руби оставља утисак јасноће и једноставности. Пример једноставности синтаксе:

Претпоставимо да желимо да пошаљемо поруку напуни_гориво објекту мој_ауто уколико резервоар није пун:

 moj_auto.napuni_gorivo unless moj_auto.spremnik_pun? 

Приметимо да је синтакса једноставна, без сувишних знакова у запису наредбе, за разлику од синтаксе других програмских језика.

Руби-“програмеров најбољи пријатељ” [9][уреди]

Руби је замишљен као програмски језик који олакшава рад програмеру лакоћом коришћења, једноставношћу и флексибилношћу. Усмереност на програмера очита је у свим деловима програмског језика. Најочитији пример за то је могућност писања кода на више различитих начина. Ево неколико примера:

  puts “Hello,world” или puts(“Hello,world”)
  {“jedan”, “dva”, “tri”} 

Тестови[уреди]

Исправљање грешака у коду (енг. bug) врло је тежак посао, нарочито након што се заврши развој и крајњим корисницима програм преда на употребу. Најбоље је открити што већи број грешака приликом саме израде програма. Руби омогућава писање тестова који тестирају изворни кôд. То је нова програмерска парадигма која омогућава бржи развој и самим тим мање трошкове развоја програма.Програмери који пишу програме у програмском језику Руби врло се често користе тестовима и они су интегрални дио сваког озбиљног проширења или програма.

Покретање програма[уреди]

Најједноставнији је начин покретања кода креирање датотеке с програмским кодом и покретање те датотеке наредбом рубѕ. Датотеке које садрже кôд написан у програмском језику Руби обично (по договору) имају екстензију .rb.

  ruby мој_програм.rb 

Основе програмског језика Руби[уреди]

Променљиве[уреди]

Променљива је симболичко име којем је придружена нека вредност. Променљива је својеврсно складиште (део меморије рачунара) у којем се налази неки податак.

  >> moja_promenljiva = 7 

Том је наредбом променљивој која се зове моја_променљива придружена вредност 7. Ако се након тога у неком изразу употреби име моја_променљива, интерпретер ће из меморије рачунара узети вредност променљиве моја_променљива (која у том случају износи 7) и укључиће је у израз на месту на којем се спомиње.

  >> puts moja_promenljiva * 2 
  14

Вредност променљиве се може мењати. Приступ променљивој којој није придружена вредност резултира поруком о грешци.

Типови података[уреди]

Сваки податак је одређеног типа. Основни типови података у програмском језику Руби јесу бројеви, низови знакова (енг. string) и поља (енг. аrrays).

Низови знакова(стринг)[уреди]

Низови знакова (енг. string) могу се у програмском језику Руби написати на више начина. Најчешће се користе двоструки наводници:

  >> "ovo je string"
  => "ovo je string" 

Двоструки наводници омогућавају уметање и извршавање израза унутар самог стринга:

  >> "Ja imam #{100 + 100} dinara" 
  => "Ja imam 200 dinara"

Низови знакова могу се написати и користећи једноструке наводнике. У том случају није могуће у низове знакова уметати и извршавати изразе те уписивати посебне знакове:

  >> puts 'Ja imam #{100 + 100} dinara\ndrugi red'
  Ja imam #{100 + 100} dinara\ndrugi red

У програмском језику Руби nil представља непостојећу или недефинисану вредност.

Hash-таблице(поља)[уреди]

Тип података под називом поље (енг. hash) сличан је низу, али за кључеве можемо користити било коју вредност. Низ има свој редослед, па ако прескочимо индекс, стварају се вредности нил. Код поља то није случај будући да индекс може бити било који тип података па не може бити речи о очекиваном редоследу индекса. Поље се дефинише употребом витичастих заграда:

  >> a = {} 
  => {}

Вредности унутар поља додају се на исти начин као и код низова:

  >> a["kljuc"] = "Vrednost" 
  => "Vrednost"
  >> a 
  => {"kljuc"=>"Vrednost"} 

Поље можемо дефинисати и тако да му одмах доделимо вредност:

  >> boja_kose = { 
     'ivan' => 'plava', 
     'marija' => 'crna', 
     'suzana' => 'plava'
  }

Карактеристика програмског језика Руби су и симболи: Симбол најчешће представља неки објекат из реалног света. Сличан је низу знакова, али заузима мање меморије. Назив симбола почиње двотачком и затим се наставља као низ знакова и бројева.

  boja_kose= {
   :ivan => 'plava',
   :marija => 'crna',
   :suzana => 'plava', 
   :petar => 'crvena' 
  }

Контролне структуре и петље[уреди]

IF[уреди]

Контролна структура се може користити на више начина: Основни начин:

  >> if (2 > 1) then 
  >> puts "istina"
  >> end 
  istina 
  => nil 

Свака контролна структура мора завршити изразом end. Заграде и кључна реч then нису обавезни, а можемо све написати у једном реду одвајајући изразе тачком са зарезом:

  >> if 2 > 1 ; puts "istina"; end 
  istina 
  => nil 

Ако имамо само једну наредбу коју желимо извршити у случају да је тест истинит, можемо користити следећи начин писања:

  >> puts "istina" if 2 > 1 
  istina 
  => nil 

Контролној структури if можемо додати кључну реч else као и у многим другим програмским језицима:

  >> if 5 > 10
  >> puts "istina" 
  >> else 
  >> puts "nije istina" 
  >> end 
  nije istina 
  => nil 

Руби подржава и кључну реч unless која има супротан учинак од кључне речи if и намењена је побољшавању изгледа и читљивости кода:

  >> puts "nije istina" unless 2 < 1 
  nije istina 
  => nil

WHILE/UNTIL[уреди]

Контролне структуре while и until користе се слично као у осталим програмским језицима:

  >> a = 0 
  => 0 
  >> while a < 5 
  >> puts a 
  >> a = a + 1 
  >> 
  end 
  0 
  1 
  2
  3 
  4 
  => nil 

Контролна структура until ради обратно од контролне структуре while:

  >> a = 0 
  => 0 
  >> until a > 5 
  >> print a 
  >> a = a + 1 
  >> end 
  0 1 2 3 4 5 
  => nil

Системске наредбе[уреди]

Руби омогућава извршавање системских наредби у љусци оперативног система[10] на следећи начин:

  >> system "echo Ovo je sistemska naredba unutar ljuske" 
  Ovo je sistemska naredba unutar ljuske
  => true

Излаз наредбе исписује се на екран. Ако је наредба успешно извршена, тј. ако је повратни кôд једнак нули, враћа се вредност true. У свим осталим случајевима враћа се вредност false. Ако желимо записати излаз од системске наредбе у неку променљиву, то можемо учинити на следећи начин:

  >> a = `echo Ovo je naredba unutar ljuske`
  => "Ovo je naredba unutar ljuske\n" 
  >> puts a
  Ovo je naredba unutar ljuske 
  => nil 

Успешност извршења наредбе (излазни кôд) можемо проверити на следећи начин:

  >> $?.exitstatus
  => 0

Нула значи да је наредба успешно извршена, а сви остали кодови означавају грешку. Напомена: Имена константи у програмском језику Руби се састоје искључиво од великих слова.

Вишеструко придруживање вредности променљивима[уреди]

Понекад желимо доделити више различитих вредности у више различитих променљивих. То чинимо на следећи начин:

  >> a, b, c = 1, 2, 3
  => [1, 2, 3] 

Уколико на десној страни знака за додељивање постоји више вредности које су одвојене зарезима, из њих се ствара низ. Након тога чланови низа придружују се редом променљивима на левој страни. Проучимо што се догађа ако на десној страни израза има више вредности него што има променљивих на десној страни:

  >> a,b = 1,2,3 
  => [1, 2, 3] 
  >> a => 1 
  >> b => 2 

У овом случају број три није придружен ниједној променљивој. Проучимо шта се догађа у супротном случају – ако је на левој страни наведено више променљивих него што има вредности на десној страни:

  >> c = 100 
  => 100
  >> a, b, c = 1, 2 
  => [1, 2] 
  >> c 
  => nil

Будући да није било довољно вредности на десној страни, променљивој c придружена је вредност nil (Null). Претходна вредност променљиве c (број 100) није сачувана. У програмском језику Руби могуће је заменити вредности променљивих на једноставнији нацин без коришћења додатне, привремене променљиве:

a, b = b, a

Класе и методи[уреди]

Класе су заокружене целине које се састоје од кода који је потребан за извршавање одређеног задатка. Дефинисање класа заправо представља дефинисање кода. Класу креирамо користећи кључну реч class и након тога навођењем имена класе. Име класе мора почети великим словом. Након што смо навели име класе, дефинишемо све методе које класа садржи и на крају додамо кључну реч end. Метода је део кода који извршава одређени задатак унутар класе. Методе су саставни део сваке класе. Дефинисање класе у ствари значи дефинисање метода. Креираћемо класу Аутомобил која се састоји од методе светла која исписује "Укључујем светла".

  >> class Automobil
  >> def svetla 
  >> puts "Uključujem svjetla" 
  >> end 
  >> end 

Постоје одређена правила при именовању метода. Имена метода које нешто проверавају и враћају логичку вредност најчешће завршавају упитником.

  >> niz = ["a","b","c"] 
  => ["a", "b", "c"] 
  >> niz.include?("a")
  => true 

У овом примеру метода include? проверава да ли је неки објекат члан низа или није. Имена метода које мењају вредност променљивих над којима су позване најчешће завршавају узвичником:

  >> a = "Srce"
  => "Srce" 
  >> a.upcase 
  => "SRCE"
  >> a => "Srce"
  >> a.upcase! 
  => "SRCE"
  >> a 
  => "SRCE"

У програмском језику Руби могуће је дефинисати методе без навођења имена класе којој метода припада. Следећи пример показује такав случај:

  >> def moje_vrijeme 
  >> puts "Sada je #{Time.now}" 
  >> end 
  => nil

Поред метода инстанце, које се позивају након што смо креирали објекат, постоји још једна врста метода које се зову методе класе или статичке методе (енг. static method). Такве методе се дефинишу коришћењем кључне реци self. Испред имена. Пример:

  >> class Automobil 
  >> def self.boje 
  >> %w( crvena zelena bela plava crna ) 
  >> end 
  >> end

Тако дефинисану методу боје можемо испробати на самој класи:

  >> Automobil.boje 
  => ["crvena", "zelena", "bijela", "plava", "crna"]

Дефинишимо две методе поздрав: једну као методу класе, а другу као методу инстанце. Нека класа има име Квадрат.

  >> class Kvadrat 
  >> def self.pozdrav 
  >> puts "Pozdrav od klase Kvadrat!" 
  >> end 
  >> def pozdrav 
  >> puts "Pozdrav od objekta klase Kvadrat!" 
  >> end 
  >> end

Позовимо методу класе:

  >> Kvadrat.pozdrav 
  Pozdrav od klase Kvadrat! 

Позовимо методу инстанце:

  >> Kvadrat.new.pozdrav 
  Pozdrav od objekta klase Kvadrat! 

У пракси се већина метода дефинише као методе инстанце, а тек се у ретким случајевима креирају методе класе. На пример, листа могућих боја универзална је за сваки аутомобил па смо зато методу боје креирали унутар класе Аутомобил. Као што постоје променљиве инстанце, тако у програмском језику Руби постоје и променљиве класа. Имена променљивих класа почињу с два знака @ (@@), за разлику од имена променљивих инстанци чија имена почињу с једним знаком @. Досег променљивих класа је цела класа, за разлику од променљивих инстанци чији је досег објекат којем припадају. Променљиве класа су корисне ако желимо забележити неки податак који се односи на целу класу.

Објекти[уреди]

Објекат је конкретна имплементација или реализација неке класе. Креирање објекта:

  moj_auto=Automobil.new

Методе које служе за креирање објеката одређене класе зову се конструктори. Конструктори се такође могу позивати наводећи аргумент, чиме нам омогућавају да поставимо почетне вредности сваком новом објекту који креирамо.

“Све је објекат”:

У програмском језику Руби све је објекат, укључујући и основне типове података. Служећи се методом class, можемо дознати којој класи припада неки објекат. Децимални бројеви припадају класи Float:

  >> 2.1.class 
  => Float 

Број два је објекат класе Fixnum:

  >> 2.class 
  => Fixnum

Чак је и nil објект:

  >> nil.class 
  => NilClass 

Атрибути и променљиве[уреди]

Сваки објекат који креирамо из одређене класе обично садржи променљиве које одражавају његово стање. Такве променљиве се зову променљиве инстанце (енг. instance variables) и њихово име почиње знаком @. Дакле, иако можемо направити више објеката из класе Аутомобил, сваки од тих објеката ће имати своје властите променљиве. Претпоставимо да желимо забележити неке карактеристике аутомобила као што су произвођач, модел, година производње, снага мотора, боја или број пређених километара. Све те карактеристике одређеног конкретног аутомобила записаћемо у променљиве инстанце. Променљивима инстанце не можемо приступити директно већ путем метода. Пример:

  >> class Automobil 
  >> def postavi_boju(x)
  >> @boja = x 
  >> end 
  >> def ocitaj_boju 
  >> @boja 
  >> end 
  >> end

Програмски језик Руби користи приступнике атрибутима ради једноставнијег И читљивијег кода. Пример:

  class Automobil 
  attr_accessor :proizvodjac, :model, :godina_proizvodnje, :snaga_motora, :prijedjeni_kilometri 
  end

Кључна реч attr_accessor класи додаје методе које омогућавају читање и писање у именоване променљиве. Испред имена променљивих наводимо знак :

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

  >> a.proizvodjac = "Zastava" 
  => "Zastava" 
  >> a.model = "Fićo" 
  => "Fićo" 
  >> a.godina_proizvodnje = 1971 
  => 1971 
  >> a.snaga_motora = 10 
  => 10 
  >> a.predjeni_kilometri = 0 
  => 0

Наслеђивање[уреди]

Многе класе сличне су једна другој тако да нема потребе дефинисати све методе у свакој класи. Можемо прво дефинисати генералну класу са свим главним методама. Након тога можемо креирати специфичне класе које имају још неке посебне функције. На пример, уколико желимо дефинисати класу Кабриолет можемо узети све методе из постојеће класе Аутомобил и додати још неке посебне методе. Ако желимо да нека класа наследи све методе из неке друге класе, у први ред дефиниције додаћемо знак < иза имена класе коју дефинишемо и навести име класе од које се наслеђују методе. У следећем примеру дефинисаћемо класу Кабриолет која наслеђује све методе класе Аутомобил и има једну додатну методу за спуштање крова:

  class Kabriolet < Automobil 
  def spusti_krov 
  puts "Spuštam krov!" 
  end 
  end 

На овај начин избегавамо умножавање кода. Ако су две класе сличне, можемо креирати заједничке методе у заједничкој класи и онда свака од класа може наследити методе из заједничке класе и имати још неке додатне.

Уланчавање метода[уреди]

Попут израза и методе се у програмском језику Руби могу уланчавати. Претпоставимо да низ знакова желимо исписати великим слова обрнутим редоследом. Један од начина је следећи:

  >> a = "Ovo je string"
  => "Ovo je string" 
  >> a = a.upcase! 
  => "OVO JE STRING" 
  >> a = a.reverse! 
  => "GNIRTS EJ OVO" 
  >> puts a 
  GNIRTS EJ OVO 
  => nil 

Користећи уланчавање метода исти резултат можемо постићи у само једном реду:

  >> puts "Ovo je string".upcase.reverse 
  GNIRTS EJ OVO 
  => nil

Блокови и итератори[уреди]

Блокови и итератори једна су од специфичности програмског језика Руби. У другим програмским језицима постоје функције и процедуре које позивамо једним или с више аргумената. Ти аргументи могу бити бројеви, низови знакова и други типови података. Међутим, у програмском језику Руби могуће је као параметар задати не само податке већ и сам програмски кôд. Заокружени кôд који можемо посматрати као целину се зове блок. Дефинишимо једноставну методу:

  >> def novi_blok 
  >> puts "Početak ponavljanja." 
  >> yield 
  >> yield 
  >> puts "Kraj ponavljanja." 
  >> end 
  => nil 

У горњем смо примеру дефинисали методу нови_блок. Посебност је те методе да садржи кључну реч yield која извршава блок који је послат у позиву те методе. Позваћемо методу коју смо управо дефинисали наводећи као аргумент при позивању те методе други програмски кôд - блок. Тај се блок састоји од само једне наредбе која исписује "Поздрав свима!":

  >> novi_blok{ puts "Pozdrav svima!" } 
  Početak ponavljanja.
  Pozdrav svima!
  Pozdrav svima!
  Kraj ponavljanja.

Дакле, блокови се не третирају на исти начин као други аргументи који се преносе функцијама. Аргументи који нису блокови евалуирају се пре позива функције док се блокови евалуирају тек приликом позива методе ѕиелд у телу функције. Блок може примати аргументе сваки пут када га извршимо, па се блокова користе најчешће за имплементацију итератора. Итератор је специјална метода која извршава блок на сваком члану низа. На пример: a| puts a.upcase >> end

  ZGRADA 
  ULICA
  CESTA 
  => ["zgrada", "ulica", "cesta"] 

Прво смо дефинисали низ који се састоји од три члана. Сваки од тих чланова је низ знакова. Након тога смо позвали методу која је итератор који редом за сваки члан низа извршава задани блок предајући му наведеног члана низа као параметар. Исто смо могли написати и на краћи начин, користећи витичасте заграде уместо кључних речи do и end: a| puts a.upcase }

Рад са датотекама[уреди]

Датотеке се у програмском језику Руби отварају на следећи начин: f = File.new("/etc/passwd","r") f.close

Датотека је отворена у модулу за читање и додељена променљивој f. Наредбом f.close затворили смо датотеку.

Читање и писање[уреди]

Метод readline чита једну линију из датотеке. Метод getc чита следећих 8 битова и претвара их у код. Методе lineno i pos служе за одређивање места на коме се налазимо у датотеци (метод lineno одређује у ком се реду налазимо, a metod pos карактер до кога смо стигли). ПРИМЕР:

file = File.new("/etc/passwd","r")
puts file.lineno
puts file.pos
file.readline
puts file.lineno
puts file.pos
puts file.getc
file.close

Ispis:

0
0
root:x:0:0:root:/root:/bin/bash
1
32
98

Za pisanje u datoteke mozemo koristiti metode: puts, print. Metod puts na kraj upisa dodaje oznaku za novi red, a metod print ne!

ПРИМЕР:

 file = File.new("/tmp/moja_datoteka", "w")
 #<File:/tmp/moja_datoteka> 
 file.puts "Prvi red"
 file.close

Датотеке можемо одмах учитати као низ карактера, без да их посебно отварамо, помоћу метода read:

a = File.read("/etc/inittab")

Класа File садржи још многе методе који се могу извршавати без отварања датотеке. На пример можемо сазнати име директоријума у које се налази датотека, име датотеке или њену величину:

 File.dirname("/tmp/moja_datoteka") 
 => "/tmp"
 File.basename("/tmp/moja_datoteka")
 => "moja_datoteka"
 File.size("/etc/passwd")
 => 2057

Рад са директоријумима[уреди]

Програмски језик Руби садржи и многе друге могућности у раду са директоријумима и датотекама. Зато га неки употебљавају као замену за програмирање у љусци оперативног система ( bash). Уколико желимо да видимо у ком директоријуму се налазимо, користимо следећу наредбу:

Dir.pw

Управљање именима датотека[уреди]

Датотекама можемо приступити и наводећи само њихово релативно име (тј. релативну путању) узимајући у обзир наш тренутни директоријум. У програмском језику Руби постоји класа Pathname, која садржи методе за управљање именима датотека. Класа Pathname је "спољашња" класа па је морамо учитати пре почетка рада:

 require 'pathname'

Објекат класе Pathname креирамо на следећи начин: (у овом примеру користимо реалтивно име датотеке уз претпоставку да се тренутно налазимо у директоријуму /root):

  p = Pathname.new("Mail")

Класа Pathname омогућава више од 70 операција над именима датотека и самим датотекама. Најзначајније од њих су:

  p.realpath    #metod vraca puno ime datoteke (odnosno apsolutnu putanju)
  p.directory?    #vraca true ako je u pitanju direktorijum, u suprotnom false
  p.file?    #vraca true ako je u pitanju datoteka, u suprotnom false
  p.basename    #izdvaja ime datoteke
  p.dirname    #izdvaja ime direktorijuma u kojem se ta datoteka nalazi

Програмски језик Руби поседује специјалну променљиву која садржи име датотеке са којом тренутно радимо. Та променљива се зове __FILE__ и и омогућава нам позивање осталих датотека које се налазе у том истом директоријуму.

Наредба File.dirname(__File__) упућује на директоријум у коме се налази програм који смо покренули.

Брисање и копирање датотека[уреди]

Метод delete користимо за брисање датотеке:

  File.delete("/tmp/moja_datoteka")

Проверу да ли постоји датотека вршимо помоћу метода exist?:

  if File.exist?("/tmp/moja_datoteka")
      File.delete("/tmp/moja_datoteka")
  End

За копирање датотека служимо се методом cp из класе FileUtils:

  FileUtils.cp("/etc/inittab","/tmp")
  • Као први аргумент наводи се име датотеке коју желимо да ископирамо
  • Као други аргумент наводимо име директоријума у који желимо да сместимо копију
  • Нова датотека ће имати име: /tmp/inittab

Уколико желимо да одједном ископирамо више датотека, као први аргумент наводи се низ:

  FileUtils.cp(["/etc/file1","/etc/file2"],"/tmp")

Класа FileUtils подржава све операције над датотекама укључујуци рекурзивно копирање, рекурзивно брисање, креирање веза и друго

Управљање грешкама[уреди]

Класа Exception[уреди]

Програмски језик Руби омогућава писање програмског кода који ће се извршити у случају да програм током извршавања наиђе на грешку. За управљање грешкама служи класа Exception. Уколико сами не одредимо шта ће програм радити у случају да се догоди нека програмска грешка, исписаће се порука са описом грешке и прекинуће се извршавање програма.

На пример, ако покушамо променљивој чија је вредност нил приступити као да је низ:

a = nil
a[0]

Испис:

 NoMethodError: undefined method `[]' for nil:NilClass

from (irb):2

Кôд за који желимо да осигурамо посебан третман у случају грешке увек почиње кључном речи begin. Следећа је кључна реч rescue и име класе или поткласе која је надлежна за врсту грешке за коју желимо посебан третман. Ако желимо да посебан третман вреди за било коју врсту грешке, наводимо класу Exception (у супротном ћемо навести неку од њених 30-так поткласа Након тога следи кôд који ће се извршити уколико програм наиђе на грешку.

На претходном примеру:

begin
  a[0]
  rescue Exception
     puts "Doslo je do greske!"
end

Резултат програма:

 Doslo je do greske!

У овом смо примеру смо само исписали да је дошло до грешке и наставили даље извршавати кôд.

Уколико уместо кључне реци rescue употребимо кључну рец raise, извршиће се кôд који следи, али након тога ће се грешка обрађивати на стандардан предефинисан нацин. У следећем примеру користимо кључну реч raise. Исписаће се порука "Грешка!" а након тога стандардна порука о грешци уз прекид извршавања програма: -{

begin
  0.upcase
  rescue Exception
  puts "Greska!"
  raise
end

Испис

  Greska!
  NoMethodError: undefined method `upcase' for
  0:Fixnum
   from (irb):2
  Konverzija uspešna

Уколико желимо да се изврши неки кôд без обзира на то је ли дошло до грешке или не, користимо кључну реч ensure:

begin
  0.upcase
  rescue Exception
  puts "Greska!"
  ensure Exception
  puts "Zatvaram datoteke"
end

Испис :

  Greska!
  Zatvaram datoteke

Горњи пример је пример уобичајене употребе кључне речи ensure (ради се о затварању датотека независно од тога је ли дошло до грешке или није). Да приликом извршавања није покренут неисправан кôд дешавало би се следеће:

begin
  0.zero?
  rescue Exception
  puts "Greska!"
  ensure Exception
  puts "Zatvaram datoteke"
end

Испис :

Zatvaram datoteke

С' обзиром на то да није дошло до програмске грешке (наредба 0.зеро? је исправна), не исписује се порука Грешка!, али се извршава део кода у којем пише Затварам датотеке.

Throw и catch[уреди]

Методом catch дефинише се програмски блок који се нормално извршава до места позива методе throw. Кад интерпретер наиђе на throw, прекида се извршавање одговарајућег програмског блока. На пример: n| if not n throw :element_nil end sum += n p sum end end

Ако извршимо овај програмски кôд, он ће резултирати следећим исписом:

1
3
6

Испис показује да се петља извршила само за прва три члана низа. Кад је петља наишла на четврти цлан низа ција је вредност нил, што одговара логичкој вредности false, извршио се метод throw и прекинуло се извршавање целог блока.

Модули[уреди]

Коришћење више датотека[уреди]

Програмски кôд могуће је поделити у више датотека (file). За укључивање кода из додатних датотека користимо require. На пример:

  require 'datoteka1'
  require 'datoteka2'

Такође, интерпретер неће приликом покретања учитати све класе које су постоје у програмском језику Руби него само основне. Стога за укључивање додатних класа такође морамо користити наредбу require. На пример, наредба require 'pathname' учитаће класу Pathname и омогућити њено коришћење.

Дефинисање модула[уреди]

Модул је изоловани кôд који се може користити у више апликација. Модули омогућавају груписање метода, класа и константи у једну целину. Креираћемо модул који садржи функцију за прерачунавање брзине задате у метрима у секунди у километре на сат:

 module Brzina
    def self.konverzija metara_u_sekundi
         metara_u_sekundi * 3.6
    end
 end

Сада можемо позвати нову функцију:

 Brzina.konverzija 10

Испис:

36.0

Примери[уреди]

Класични „Поздрав Свету":

puts "Hello World!"

Референце[уреди]

Литература[уреди]

Спољашње везе[уреди]