Liczby w Rubym, w odroznieniu od Javy, to obiekty!
# 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
# 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.rb print "Czesc, podaj mi twoje HRrest: " hrrest = gets.to_i puts "Ooo, duzo biegamy?:-)" if hrrest.between?(40, 50)
# 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
# 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" }
# 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
# 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 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.
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 = <<SZYNKA Tak tez mozna, to dobrze znany sposob z PHP SZYNKA puts x, y, z
Dobrze jest wybrac taki delimiter, zeby nie kolidowal ze znakami w cytowanym tekscie.
# 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.
# 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() 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
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.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
=~
, 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
# 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.
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!"]
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]
# 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
# array_include.rb x = ["sqbell", "lubi", "koszule", "w", "kratke"] p x.include?("w") p x.include?("dziewczyny")
Output:
true false
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.
# array_reverse.rb x = ["December.", "bleak", "a", "in", "was", "It"] puts x.reverse.join(" ")
Output:
It was in a bleak December.
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' }
# hash_iterating.rb x = { "a" => 1, "b" => 2 } x.each { |key, value| puts "#{key} equals #{value}" }
# hash_kv.rb hsh = { "first" => "Belegost", "second" => "Aiginn", "third" => "Misette"} p hsh.keys p hsh.values
Output:
["first", "second", "third"] ["Belegost", "Aiginn", "Misette"]
# 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 }
# 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']
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
# 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:
TODO rozszerzyc!
Przyklady:
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
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
).
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 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).