===== Liczby i wyrazenia ===== Liczby w Rubym, w odroznieniu od Javy, to obiekty! ==== Podstawowe wyrazenia ==== === if === # wow_life.rb print "Ile masz postaci na poziomie 85 w WoWie? " number_of_lvl_85s = gets.to_i puts "Powinienes czesciej wychodzic." if number_of_lvl_85s > 1 && number_of_lvl_85s <= 5 puts "Sprzedaj konto i zacznij zyc, na milosc boska!" if number_of_lvl_85s > 5 === unless === # facebook_friends.rb print "Ilu masz znajomych na facebooku? " fb_friends = gets.to_i puts "W sam raz." unless fb_friends < 10 || fb_friends > 20 === between === # between.rb print "Czesc, podaj mi twoje HRrest: " hrrest = gets.to_i puts "Ooo, duzo biegamy?:-)" if hrrest.between?(40, 50) === x <=> y === # comparison.rb print "Ile masz lat? " age = gets.to_i my_age = 26 reaction = age <=> my_age puts "Czesc." if reaction == -1 puts "Dzien dobry." if reaction == 1 puts "Haii!" if reaction == 0 === .times === # loops.rb 5.times do puts "Bede sie pilnie uczyl, obiecuje!" puts "I juz nigdy nie wejde na ta strone. /blushes" end Zamiast ''do'' i ''end'' mozna wykorzystac nawiasy klamrowe. Preferowane jest uzywanie klamer dla jednoliniowych blokow a ''do'' i ''end'' dla wieloliniowych. # curly_loops.rb 5.times { puts "Bede sie pilnie uczyl, obiecuje!" puts "I juz nigdy nie wejde na ta strone. /blushes" } === upto, downto, step === # iterators.rb # upto puts "== upto ==" 1.upto(5) { |number| puts number } # downto puts "== downto ==" 10.downto(5) { |number| puts number } # step puts "== step ==" 0.step(50, 15) { |number| puts number } Output: == upto == 1 2 3 4 5 == downto == 10 9 8 7 6 5 == step == 0 15 30 45 === to_f, to_i === # floating.rb x = 10 x_float = 10.0 y = 3 print "10 / 3: \t\t\t", x / y, "\n" print "10.0 / 3: \t\t\t", x_float / y, "\n" print "10.to_f / 3.to_f: \t\t", x.to_f / y.to_f, "\n" print "(x.to_f / y.to_f).to_i: \t", (x.to_f / y.to_f).to_i, "\n" Output: 10 / 3: 3 10.0 / 3: 3.3333333333333335 10.to_f / 3.to_f: 3.3333333333333335 (x.to_f / y.to_f).to_i: 3 === stale === Stale w Rubym to zmienne zaczynajace sie od duzej litery. # constants.rb # O, solitude... Have_girlfriend = 0 # ... how I hate thee... Have_girlfriend = 1 print "... but our paths, it seems, are forever to be intertwined.\n" if Have_girlfriend == 0 print "... but there is a hope! Keep your chin up.\n" if Have_girlfriend == 1 Output: constants.rb:7: warning: already initialized constant Have_girlfriend ... but there is a hope! Keep your chin up. ?! How can this be? **Stale moga byc zmieniane**, ich zmiana generuje ''warning'' ale to wszystko. Nazwy klasy takze sa pisane wielka litera i rowniez sa traktowane jak stale. ===== Tekst i lancuchy znakow ===== Lancuchy znakow (''string''i), jak w Javie, sa obiektami. Lancuch wpisany w kod, za pomoca cudzyslowow nazywany jest jako literał łańcuchowy (''string literal''). # string_literals.rb x = %q{Test zmiennej wielo liniowej. } y = %q!Zamiast klamer mozna wykorzystac inne delimitery. ! # heredoc z = < Dobrze jest wybrac taki delimiter, zeby nie kolidowal ze znakami w cytowanym tekscie. ==== Operacje na lancuchach ==== # string_expr.rb # konkatenacja season = "summer" puts "Shall I compare thee to a " + season + "'s day..." # mnozenie puts "I hate you. " * 5 # porownywanie puts "x" > "y" # ?x print "?x = ", ?x, "\n" print "?y = ", ?y, "\n" print "120.chr = ", 120.chr, "\n" Output: Shall I compare thee to a summer's day... I hate you. I hate you. I hate you. I hate you. I hate you. false ?x = x ?y = y 120.chr = x ?x nie dziala w wersji 1.9.2 - **investigate**. === Interpolacja === # interpolation.rb x = 10 y = 20 puts "#{x} + #{y} = #{x + y}" Output: 10 + 20 = 30 Mozna umieszczac wyrazenia lub nawet logike w lancuchach. Taki proces, tj. proces wstawiania wyniku wyrazenia do lancucha literalowego, nazywamy interpolacja. Robi sie to, umieszczajac wyrazenie pomiedzy ''#{'' a ''}''. === .sub(), .gsub() === .sub() zastepuje pierwsze wystapienie tekstu innym, .gsub() zastepuje wszystkie wystapienia. # sub_stitution.rb sentence = "sqbell rings a bell" puts sentence.sub('bell', 'ueal') puts sentence.gsub('bell', 'ueal') Output: squeal rings a bell squeal rings a ueal === Krotkie wprowadzenie do wyrazen regularnych === ^ Znak ^ Znaczenie ^ | ''/'' | poczatek i koniec wyrazenia regularnego | | ''^'' | kotwica (''anchor''), znacznik poczatku linii | | ''$'' | kotwica, znacznik konca linii | | ''\A'' | absolutny poczatek ciagu | | ''\Z'' | absolutny koniec ciagu | | ''.'' | dowolny znak | | ''\w'' | dowolna cyfra, litera badz podkreslenie | | ''\W'' | wszystko, czego nie obejmuje ''\w'' | | ''\d'' | dowolna cyfra | | ''\D'' | odwrotnosc ''\d'' | | ''\s'' | whitespace (spacje, tabulacje, nowe linie, etc)| | ''\S'' | j/w | ^ Modyfikator ^ Znaczenie ^ | ''*'' | zero lub wiecej, poprzedzajacych modyfikator, znakow; dopasuj najwiecej ile sie da | | ''+'' | jeden lub wiecej... | | ''*?'' | zero lub wiecej, dopasuj najmniej jak sie tylko da | | ''+?'' | jeden lub wiecej... | | ''?'' | jeden lub zero | | ''{x}'' | dopasuj dokladnie x wystapien | | ''{x, y}'' | dopasuj conajmniej x i conajwyzej y wystapien | Wiecej: http://net.tutsplus.com/tutorials/ruby/ruby-for-newbies-regular-expressions/ # regexp_01.rb x = "sqbell likes his beer like he likes his women: stout and bitter.\nAnd yes, he IS a World of Warcraft player." # zastepujemy pierwsze (^) dwa dowolne znaki (.) pierwszej (.sub()) linii puts x.sub(/^../, 'Mr '), "\n" # zastepujemy ostatnie ($) szesc dowolnych znakow pierwszej linii puts x.sub(/......$/, 'etter.'), "\n" # zastepujemy ostatnie (\Z) szesc znakow (calego) ciagu puts x.sub(/......\Z/, 'etter.'), "\n" Output: Mr bell likes his beer like he likes his women: stout and bitter. And yes, he IS a World of Warcraft player. sqbell likes his beer like he likes his women: stout and better. And yes, he IS a World of Warcraft player. sqbell likes his beer like he likes his women: stout and bitter. And yes, he IS a World of Warcraft petter. === .scan() === # scan.rb x = "sqbell likes his beer like he likes his women: stout and bitter.\n" # wyswietlamy po trzy znaki x.scan(/.../) { |letters| puts letters } puts "==========" # nie chcemy whitespace'ow! x.scan(/\w\w\w/) { |x| puts x } puts "==========" # slowa x.scan(/\w+/) { |x| puts x } puts "==========" # slowa czteroliterowe x.scan(/\w{4}/) { |x| puts x } Output: sqb ell li kes hi s b eer li ke he lik es his wo men : s tou t a nd bit ter ========== sqb ell lik his bee lik lik his wom sto and bit ter ========== sqbell likes his beer like he likes his women stout and bitter ========== sqbe like beer like like wome stou bitt === Dopasowywanie (matching) === ''=~'', podobnie jak w perlu, sluzy nam jako operator dopasowywania. # matching.rb x = "O democracy, near at hand to you my throat is inflating itself and joyfully singing" # czy jest na pokladzie jakas samogloska? puts "Mamy samogloski!" if x =~ /[aeiou]/ # to samo co powyzej puts "Mamy samogloski, inaczej!" if x.match(/[aeiou]/) # nawiasy w regexp umozliwiaja nam dostep do matchowanych danych y = x.match(/(\w+) (\w+)/) # match zwraca nam obiekt MatchData, z ktorego mozna korzystac jak # z tablicy puts y[0] # zerowy element zawiera dane dopasowane przez cale wyrazenie puts y[1] # kolejne elementy zawieraja dane dopasowane przez kolejne puts y[2] # wyrazenia ujete w nawiasy Output: Mamy samogloski! Mamy samogloski, inaczej! O democracy O democracy ===== Tablice i listy ===== # arrays.rb x = [1, 2, 3, 4] puts x[2] # wstawianie elementow do tablicy y = [] # definicja pustej tablicy, to samo co y = Array.new y << "I rulezZz." # to to samo co y.push("You suck.") y << "kk?" # pop pobiera i usuwa ostatni element tablicy puts y.pop puts y.length # join laczy wszystkie elementy tablicy; # opcjonalny parametr wskazuje delimiter puts x.join(', ') puts y.join(' ') Output: 3 kk? 2 1, 2, 3, 4 I rulezZz. You suck. ==== .inspect() i p ==== Obydwie metody doskonale sprawdzaja sie w podgladaniu obiektow, tablic i tak dalej. ''inspect'' przedstawia tekstowa reprezentacje obiektu. ''p'' dziala na podobnej zasadzie. Cos jak print_r w PHP. # str_to_array.rb p "Jestes jak melodia tkliwa, slodko z najczystszych grana nut.".scan(/\w+/) puts "To be a ruler of life, not a slave!".split(/ /).inspect ["Jestes", "jak", "melodia", "tkliwa", "slodko", "z", "najczystszych", "grana", "nut"] ["To", "be", "a", "ruler", "of", "life,", "not", "a", "slave!"] ==== Iteratory .each i .collect ==== http://stackoverflow.com/questions/3630670/ruby-on-rails-distinct-difference-between-collection-and-each Roznica jest taka, ze .collect (oraz, jak sie okazuje, .map) zwracaja nowa tablice, podczas gdy .each modyfikuje stara. # array_iteration.rb # each x = [1, 2, 3, 4] x.each { |element| element * 2 } p x puts "========" # collect y = [1, 2, 3, 4] z = y.collect { |element| element * 2 } p y p z Output: [1, 2, 3, 4] ======== [1, 2, 3, 4] [2, 4, 6, 8] ==== Dodawanie, odejmowanie tablic, empty? ==== # combine_array.rb x = ["Ala", "ma"] y = ["kota", "a", "kot"] z = ["ma", "Ale"] a = x + y + z p a # odejmowanie tablic x = [1, 2, 3, 4, 5] y = [1, 2, 3] z = x - y p z # .empty? x = [] puts "x jest pusta" if x.empty? Output: ["Ala", "ma", "kota", "a", "kot", "ma", "Ale"] [4, 5] x jest pusta ==== .include? ==== # array_include.rb x = ["sqbell", "lubi", "koszule", "w", "kratke"] p x.include?("w") p x.include?("dziewczyny") Output: true false ==== .first, .last ==== Jako parametr, mozna podac liczbe zwracanych elementow od poczatku (lub konca) tablicy. # array_fl.rb x = "Lubie duze, ciezkie i stare zolwie".scan(/\w+/) print "#{x.first} #{x.last}.\n" print "#{x.first(2).join(" ")} #{x.last(3).join(" ")}.\n" Output: Lubie zolwie. Lubie duze i stare zolwie. ==== .reverse ==== # array_reverse.rb x = ["December.", "bleak", "a", "in", "was", "It"] puts x.reverse.join(" ") Output: It was in a bleak December. ===== Hashe ===== W odroznieniu do tablic, gdzie kazdemu elementowi przyporzadkowany jest indeks, pozycja na liscie, w przypadku hashy, jest to klucz (''key''), ktory na element wskazuje. Nie ma tu zagwarantowanej kolejnosci. W wersji 1.9 Rubiego jednakowoz, kolejnosc, z jaka elementy byly wstawiane do hasha jest zapamietywana i ''each'' zwroci je w tej kolejnosci. # hash_basics.rb hash_pipe = { 'band' => 'Weezer', 'status' => 'sucky' } ==== Iterowanie poprzez hasha ==== # hash_iterating.rb x = { "a" => 1, "b" => 2 } x.each { |key, value| puts "#{key} equals #{value}" } ==== .keys, .values ==== # hash_kv.rb hsh = { "first" => "Belegost", "second" => "Aiginn", "third" => "Misette"} p hsh.keys p hsh.values Output: ["first", "second", "third"] ["Belegost", "Aiginn", "Misette"] ==== .delete, .delete_if ==== # hash_delete.rb x = { "a" => 1, "b" => 2 } x.delete("a") # hash_delete_if.rb x = { "a" => 100, "b" => 20 } x.delete_if { |key, value| value < 25 } ==== Hashe w hashach ==== # hash_in_hash.rb people = { 'fred' => { 'name' => 'Fred Elliott', 'age' => 63, 'gender' => 'male', 'favorite painters' => ['Monet', 'Constable', 'Da Vinci'] }, 'janet' => { 'name' => 'Janet S Porter', 'age' => 55, 'gender' => 'female' } } puts people['fred']['age'] puts people['janet']['gender'] ===== Sterowanie przebiegiem programu ===== ==== elsif, case ==== W przypadku ''case/when'', nie trzeba przerywac wykonywania (''break'' w PHP). # elsif_case.rb fruit = "orange" if fruit == "orange" color = "orange" elsif fruit == "apple" color = "green" else color = "unknown" end fruit = "orange" case fruit when "orange" color = "orange" when "apple" color = "green" else color = "unknown" end ==== Bloki kodu ==== # code_blocks.rb x = [1, 2, 3] x.each { |y| puts y} W powyzszym przypadku kod bloku znajduje sie pomiedzy klamrami (moze tez znajdowac sie pomiedzy delimiterami ''do'' i ''end''). Kod ten to anonimowa metoda lub funkcja. Jest on podawany do metody ''each'', ktora z kolei uruchamia ten kod dla kazdego elementu tablicy. Metoda, ktora przyjmuje takie bloki kodu wygladac moze nastepujaco: # code_blocks_method.rb def each_vowel(&code_block) %w{a e i o u}.each { |vowel| code_block.call(vowel) } end each_vowel { |vowel| puts vowel} Pierwsze trzy linie to metoda, ktora przyjmuje blok kodu jako parametr(?), co jest okreslane za pomoca znaku ''&''. W tej metodzie, iterujemy po elementach specjalnej tablicy ''%w'' (omowionej w dalszej czesci), dla kazdego wywolujac blok kodu podany jako parametr za pomoca metody ''code_block.call''. To samo mozna osiagnac za pomoca metody ''yield''. # code_blocks_yield.rb def each_vowel %w{a e i o u}.each { |vowel| yield vowel } end each_vowel { |vowel| puts vowel} Tylko jeden blok kodu moze byc podawany metodzie. Bloki kodu natomiast, moga przyjmowac parametry. Mozna przechowywac bloki kodu w zmiennych za pomoca metody ''lambda''. # code_blocks_lambda.rb print_parameter_to_screen = lambda { |x| puts x } print_parameter_to_screen.call(100) Wiecej przykladow: * http://blog.codahale.com/2005/11/24/a-ruby-howto-writing-a-method-that-uses-code-blocks/ * http://en.wikipedia.org/wiki/Ruby_%28programming_language%29#Blocks_and_iterators * http://blog.rubybestpractices.com/posts/gregory/009-beautiful-blocks.html === % === TODO rozszerzyc! Przyklady: * http://old.blog.jimhoskins.com/?p=8 * http://stackoverflow.com/questions/5751831/percent-notation-in-ruby ===== Inne przydatne rzeczy ===== ==== Daty i czas ==== Sprytni programisci, aby ulatwic sobie sprawe z operacjami na datach, rozszerzaja klase Fixnum o nastepujace metody. Dzieki temu, kod jest duzo bardziej czytelny i zrozumialy. # date_fixnum.rb class Fixnum def seconds self end def minutes self * 60 end def hours self * 60 * 60 end def days self * 60 * 60 * 24 end end puts Time.now puts Time.now + 10.minutes puts Time.now + 16.hours puts Time.now + 7.days ^ Metoda ^ info ^ | ''Time.local(year, month, day, hour, min, sec, msec)'' | Kod tworzy instancje obiektu ''Time'' na podstawie lokalnej strefy czasowej | | ''Time.gm(...)'' | GMT/UTC | | ''Time.utc(...)'' | dokladnie jak powyzej | Aby zamienic obiekt ''Time'' na liczbe sekund od epoku UNIXa (lub z powrotem) # time_to_unix.rb puts Time.local(2011, 05).to_i puts Time.at(Time.local(2011, 05).to_i).year ==== Duze liczby ==== W rubym nie trzeba sie martwic duzymi liczbami. Sa one obslugiwane przez klase ''Bignum'' niemalze bez wiedzy uzytkownika. Granica pomiedzy ''Fixnum'' a ''Bignum'' zalezna jest od architektury systemu. (mozna to sprawdzic, testujac liczby: ''puts 1073741824.class''). ==== Przedzialy ==== Opcje -Ku wlaczaja obsluge UTF-8. #!/home/sqbell/.rvm/rubies/ruby-1.9.2-p180/bin/ruby -Ku # utf_8.rb (0x0000 .. 0x7f).each { |letter| puts "0x#{letter.to_s(16)}: #{letter.chr} " } Output: [...] 0x6d: m 0x6e: n 0x6f: o 0x70: p 0x71: q 0x72: r 0x73: s [...] # ranges.rb puts ('a' .. 'z').include?('r') a = [2, 4, 6, 8, 10, 12] p a[1 .. 3] a[1 .. 3] = ["a", "b", "c"] p a Output: true [4, 6, 8] [2, "a", "b", "c", 10, 12] ==== Symbole ==== Symbole nie posiadaja wartosci czy obiektu, jak zmienne. Sa uzywane jako stale nazwy w kodzie. Poprzedzamy je dwukropkiem ('':''). # symbols.rb current_situation = :good puts "Everything is fine." if current_situation == :good puts "PANIC! Run for your life!" if current_situation == :bad Mozna by zamiast symboli uzyc lancuchow znakow (''"good"'', ''"bad"''), ale jest to mniej wydajne (lancuch znakow to obiekt a symbol to zwykla referencja do wartosci, ktora jest inicjowana tylko raz).