User Tools

Site Tools


inf:ruby:rozdz_3

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 (stringi), 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.

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:

%

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).

inf/ruby/rozdz_3.txt · Last modified: 2021/02/16 09:56 (external edit)