Ruby - wprowadzenie

(30 komentarzy)

W kategoriach: Ruby , Ruby tutorial , Techblog / 27 marca 2007 [23:15:47]

Tagi technorati:

Disclaimer: Tekst ten jest prezentacją języka Ruby dla tych, którzy jeszcze się z nim nie zetknęli. Dla pozostałych będzie on niewiele (lub nic) wnoszącym artykułem o tym, co już nie raz zostało poruszone. Czym ten post różni się od innych, traktujących o tej samej tematyce? Niczym. Jest to moje własne spojrzenie na ten język, manifest wielkiego entuzjazmu z nim związanego oraz próba zaprezentowania Rubiego większej liczbie programistów. Bo jest co pokazywać.

Yukihiro Matsumoto a.k.a. Matz, twórca Rubiego, po raz pierwszy wypuścił swój klejnot na świat w roku 1995. Pragnął stworzyć język o potężnych możliwościach, bardziej obiektowy niż ówczesne języki skryptowe, nadający się do codziennych zastosowań wszelkiego typu oraz sprawiający, że programowanie to czysta przyjemność, a nie naginanie topornej składni w celu osiągnięcia żądanego rezultatu. Wszystko to udało mu się osiągnąć. I znacznie więcej.

Co takiego sprawia, że Ruby jest wyjątkowy?

Wszystko jest obiektem

Stwierdzenie to jest nie do końca prawdziwe, ale to teraz nieistotne. Ruby miał być z założenia w pełni obiektowy. Każda liczba (czy to całkowita czy zmiennoprzecinkowa), tablica czy string to obiekt. Nawet nil (odpowiednik NULL-a z PHP czy C) jest obiektem. Jakże to tak? nil to przecież nic! Owszem. W Rubim reprezentujemy to za pomocą obiektu, który modeluje „nic”.

# To jest komentarz w Ruby. 
# Komentarz za każdą instrukcją niech oznacza
# dla nas to, co instrukcja daje na wyjściu
puts 5.class                  # Fixnum
puts (1.2).class              # Float
puts "tekst".class            # String
puts (2..5).class             # Range
puts -3.abs                   # 3
puts (-5.3424).round          # -5
puts "Ala ma chomika".length  # 14
puts 6.zero?                  # false

Osobom nadal uważającym, że ich kochane C++ czy PHP jest w pełni obiektowe, polecam pójście do kąta i przemyślenie sprawy raz jeszcze.

Ruby jest językiem dynamicznym…

…i bynajmniej nie oznacza to tego, że oferuje jedynie dynamiczną typizację. Skoro każda liczba jest obiektem, spróbujmy sprawdzić nieparzystość 5:

puts 5.odd?
test.rb:15: undefined method `odd?' for 5:Fixnum (NoMethodError)

Błąd? Nie szkodzi. Ruby jest dynamiczny.

class Integer
  def odd?
    (self % 2) == 1
  end
end

puts 5.odd?       # true
puts 6.odd?       # false
puts 7.odd?       # true

Nie trzeba chyba mówić, jak potężnym to może być narzędziem w rękach wprawnego programisty. Dzięki temu nie ma najmniejszego problemu, by liczby rzeczywiste rozszerzyć o część urojoną, a URL-e zacząć traktować jak zwykłe pliki.

Ruby jest językiem przejrzystym i naturalnym

A oto parę przykładów. Ciekawsza część opatrzona została tym, co skrypt daje na wyjściu - pozostałe przykłady są oczywiste nawet dla tych, którzy Rubiego nie znają.

5.times do
  puts "Ruby!"
end
for i in 1..5 
  puts i
end
5.downto(1)  { |i| puts i }
a = 5
# Pierwsze podejście
unless a == 5
  puts "a != 5"
else
  puts "a = 5"
end
# Drugie podejście
if a == 5 then
  puts "a = 5"
else
  puts "a != 5"
end
# Trzecie podejście
puts "a = 5" if a == 5
animals = ["kot", "pies", "chomik", "surykatka"]
animals.each { |animal| puts animal }
puts defined? animals
kot
pies
chomik
surykatka
local-variable
File.open "test.rb" do |file|
  file.each_line { |str| puts str }
end

Kod Rubiego jest nie tylko przejrzysty, ale i zwięzły

W Sieci nietrudno znaleźć listingi parolinijkowych programów, które napisane w innych językach zajmują ich wielokrotnie więcej. Przykłady podane wyżej pokazały, że jest to możliwe, ale jak widać to nie koniec:

def bizarre_proc
  yield
  yield
  yield
  puts "A masz! jeszcze raz!"
  yield
end

bizarre_proc { puts "Bum!" }
bizarre_proc do
  5.times { |i| puts i}
  puts "I jeszcze jeden!"
end

Pokazywanie outputu jest pozbawione sensu (jest zbyt długi) - sprawdźcie u siebie co ten kod produkuje. :)

Jedną z ważniejszych zasad Rubiego jest DRY. Jak widać, yield doskonale ułatwia realizację tej wskazówki. Instrukcja ta ma wiele potężnych zastosowań, które wkrótce poznamy.

Ruby jest obiektowy. I jest Rubim

Tak, to już było. Tyle, że Ruby oferuje masę wspaniałych rozwiązań. Duck typing pozwala na zajęcie się funkcjonalnością, a nie martwieniem się o interfejsy. Moduły dają nam przestrzenie nazw, miksiny oferują przejrzystszy odpowiednik dziedziczenia wielokrotnego, a wszystko to jest podane w zwięzłej i, nie oszukujmy się, pięknej składni Rubiego, dającej tyle możliwości i usprawnień, że nie sposób tego tu i teraz zaprezentować. Tym razem nie będzie przykładowego kodu, po prostu uwierzcie mi na słowo.

Ruby może naprawdę wszystko…

…a to za sprawą licznych modułów i bibliotek. Nie tylko standardowych. Aplikacje webowe? GUI? OpenGL? XML? Automatyzacja systemu? Win32 API? Bez najmniejszego problemu.

Nic nie stoi na przeszkodzie, by samemu napisać rozszerzenie do Rubiego w C, lub wykorzystać ten język do oskryptowania sztucznej inteligencji w swojej grze komputerowej. Wszystko oczywiście prościej, niż znamy to z innych języków.

Ruby jest Twoim przyjacielem…

…bo tylko przyjaciel może się okazać tak pomocny i zaoferować m. in.:

  • irb – interaktywną powłokę Rubiego, przydatną nie tylko przy poznawaniu tego języka
  • ri – dokumentację języka
  • gem – system zarządzania pakietami i bibliotekami

Chcesz użyć modułu RedCloth, którego nie posiadasz w swojej dystrybucji Rubiego?

gem install RedCloth

Moduł zostanie pobrany z Sieci i automatycznie zainstalowany; zupełnie jak w BSD czy Gentoo.

Ruby posiada swoje Rails…

…czym nie może się pochwalić żaden inny język. Prosty system blogowy napisany w 15 minut? No problem, nawet z objaśnieniami każdej linijki kodu. Nie wierzysz? Więcej takich smaczków znajdziesz tutaj.

Ruby ma fajną nazwę :-)

W czym programujesz? C? D? Ą? PHP? A ja w Rubim. I kto tu jest lepszy? ;-)

A teraz czas na pierwszy program...

...bo czym byłaby pierwsza część tutoriala bez tego?

def hello(name)
  puts "Hello, #{name.capitalize}!"
end

hello "ruby"
Hello, Ruby!

Witajcie w świecie Rubiego. Klik.

Komentarze: Skocz na dół, na górę

  1. Miłe i przejrzyste wprowadzenie do rubiego. :-)

    Potencjalnych „nowych” wyznawców Rubymanii może faktycznie zainteresować. ;-)

    Planujesz więcej artykułów tego typu?

    Pozdrawiam,Rafał.

  2. Owszem, planuję. Cały blog chcę poświęcić w dużej mierze Rubiemu i Railsom, jak wskazuje na to nazwa :).

  3. Pozostaje mi kibicować. :-)

    Chociaż ja sam, przeglądając zasoby internetu uważam, że naprawdę ciężko jest zastąpić dobrą książkę, np. Pickaxe czy „Agile Web development in Rails”.

  4. Obie mam :).

    Nauka z książek jest specyficzna, aczkolwiek sam nie wyobrażam sobie uczenia się czegokolwiek bez książek, i to nie tylko programowania. Są jednak osoby, które wolą się uczyć szybko, mniej dokładnie, a biegłość sobie wyrabiać nie na rzetelnym czytaniu cegieł, a na praktyce. Nie da się ukryć, że swoje artykuły będę adresował do tej właśnie grupy, ale postaram się być dokładny i nie pomijać żadnego istotnego elementu. :)

  5. Gratulacje. Bardzo dobry, a zwłaszcza konkretny wstęp. Będę śledził na bieżąco nowe wpisy :)

  6. Gdy poznawałem Rubiego to bardzo mi pomagała konsola irb, polecam z niej korzystać.
    Oby, tak dalej, tak dalej ….

  7. zjadło mi komentarz :>

  8. Jeden z byłych joggerowiczów produkuje tutorial do rubina: http://www.stifflog.com/pl/ruby.html

  9. Czytałem, bardzo fajne. Szczególny szacunek należy się autorowi za to, że zaczął pisać o Rubym, kiedy ten był znany tylko nielicznym programistom w Polsce.

  10. Dwie sprawy:
    1. Rails mają odpowiedniki w Pythonie oraz w PHP – tam też można napisać system blogowy w 15 minut.
    2. „Programuję w Pythonie” też fajnie brzmi.

  11. „W czym programujesz? C? D? Ą? PHP? A ja w Rubim. I kto tu jest lepszy? ;-)”

    Podejrzewam, ze im trudniejszy jezyk ktorego uzywa programista, tym lepszy jest on. Dziecko tez potrafi postawic kolejke na eletrycznych torach, do zbudowania tej kolejki potrzeba czegos wiecej..

  12. Hej, hej! Bardzo się cieszę, że nie zacząłeś od Rails. Honor pierwszego tutoriala należy oddać samemu językowi. :) (Mógłbyś tylko zamienić miejscami sekcje o Ruby i Ruby on Rails w menu).

    Oby tak dalej, pisz więcej o czystym Rubym!

  13. „W czym programujesz? C? D? Ą? PHP? A ja w Rubim. I kto tu jest lepszy? ;-)”
    Jak to kto – perl ;-)

  14. naprawde jestem zaintrygowany. komercyjnie programuje w C# i mam wielokronie zastanawialem sie, dlaczego niektore jezyki sa bardziej popularne od innych: niestety, sam jezyk nie wystarczy. to jest swietny poczatek, niemniej jednak niezbedne jest IDE. z tego co wiem, jedna z firm obiecala rozwinac IDE dla Ruby, niemniej jednak chyba nie jest to jeszcze 1.0. mozesz potraktowac to jako propozycje do kolejnych odcinkow: przeglad narzedzi wspomagajacych. pozdr.

  15. Ja programuje w Perl, kiedy jakieś pół roku temu liznąłem Ruby nie byłem co do niego przekonany, ale ten tekst sprawił że chyba spróbuję jeszcze raz.

  16. qjaw: Rails było tworzone przez entuzjastów Rubiego. W Rails masz realizację całej filozofii tego języka i ekspozycję wszystkich jego zalet.

    Nie przeczę, że w porcie Railsów dla PHP da się napisać system blogowy w 15 minut – ale PHP jest zupełnie innym językiem niż Ruby, tak więc portowanie czegoś, co mierzy w język o innych cechach nie skazuje takiego projektu na powodzenie.

    A Python? To bardzo dobry język i on prędzej będzie w stanie udawać to, co oferuje Rails. Podkreślam jeszcze raz: udawać. Rails było pierwsze a fakt, że ten framework jest wzorem dla innych przemawia tylko i wyłącznie na korzyść Railsów. I Rubiego, bo to on został wybrany przez twórców RoRa.

    Hakamairi: Każdy język ma swoje zastosowanie. Jeśli tworzysz system operacyjny albo superwydajną grę komputerową, C będzie jak znalazł. Ale w aplikacjach webowych liczy się m. in. szybkość ich tworzenia, łatwość rozbudowy itp. Ruby jest językiem, który daje jedno i drugie – ma potężne możliwości, a przez to nie jest łatwy. Ale jest prosty – a to chyba dobrze. :)

    Sharpman: Ruby błyszczy przede wszystkim w Rails. Wg. mnie niesłusznie, bo on potrafi dużo więcej, dlatego będę starał się pisać na bieżąco o IDE dla niego.

  17. sharpman: Odnośnie IDE do Rubiego to jest już trochę niezłych IDE. Jednakże nie można zapominać, że kod Rubiego (z racji swej składni i elegancji języka) jest wielokrotnie krótszy niż jego odpowiednik w C# czy Javie. Stąd posiadanie jakiegoś rozbudowanego podpowiadacza IDE nie jest aż tak kluczowa jak w tych innych językach. W Ruby odpada proces kompilacji, kod jest wysoce dynamiczny i umożliwia pracę wręcz interaktywną.

    Co do PHP to szkoda gadać. Fatalnie zaprojektowany język, brak przestrzeni nazw, chaotyczna, niespójna składnia, nazwy i sposoby wywołania funkcji. Są oczywiście projekty naśladujące Rails w innych językach, ale daleko im do komfortu pracy jaki oferują Railsy. Siłą Railsów jest dynamizm Rubiego który przewyższa nawet to, co potrafi Python. To Ruby powoduje że kod Railsów jest tak prosty, piękny i krótki zarazem.

  18. JZ, o ile procent dynamizm R. przewyższa P. ? ;)

    Btw, autor tego jogga napisał że w Rubym wyjątkowe jest to że wszystko jest obiektem. Jest kilka a może i kilkanaście języków o których można by tak powiedzieć.

  19. s: Połącz te wszystkie wyjątkowości operatorem ‘and’ i wtedy zacznij liczyć języki, do których to wszystko na raz się aplikuje. :)

    Tekst jest nie tylko wprowadzeniem. Jest też manifestem entuzjazmu (disclaimer!), a ten bywa ślepy, nieobiektywny i krzywdzący. Niech wszyscy mają to na uwadze.

  20. mam małą uwagę tu tego tuta: nie idzie wygodnie przekleić przykładów mychą, tylko ja tak mam ?

    i jeszcze jedną: w przykładzie na konstrukcje warunkowe masz trzy podprzykłady, ale ostatni
    nie jest równoważny dwu poprzednim, a przecież można napisać tak: puts a == 5 ? "a" : "b"

    i jeszcze jedną: o co chodzi w przykładzie z dynamizmem ? możliwość zdefiniowania metody wydaje mi się rzeczą oczywistą.

    Co do zwięzłości (przykład z bizzare_proc) to faktycznie jest to imponujące, aczkolwiek można uzyskać zbliżony efekt nie korzystając z Rubego

         (defmacro bizzare (&body y)
           `(progn ,@y ,@y ,@y (format t "A masz! jeszcze raz!~%") ,@y))
    
         (bizzare (princ "Bum!") (terpri))
    
            Bum!
            Bum!
            Bum!
            A masz! jeszcze raz!
            Bum!
    
         (bizzare (dotimes (i 5) (write i) (terpri)) (format t "I jeszcze jeden!~%"))
    
            0
            1
            2
            3
            4
            I jeszcze jeden!
            0
            1
            2
            3
            4
            I jeszcze jeden!
            0
            1
            2
            3
            4
            I jeszcze jeden!
            A masz! jeszcze raz!
            0
            1
            2
            3
            4
            I jeszcze jeden!
    

    ten współczynnik (wielokrotności) o którym piszesz jest tu imho do zaakceptowania, choć oczywiście Ruby jest bardziej zwięzły o czytelności nie wspomniając…

    Faktycznie, R. jest jedynym językiem o którym słyszałem że może wszystko… co prawda brakuje mu tego, owego i siamtego a ponadto jest wolny nawet jak na język interpretowany, ale w TODO widziałem większość rzeczy których mi w R. brakowało (kiedy ostatnio sprawdzałem).

    Ruby ma swoje Rails, niemniej Smalltalk (na przykład) ma swoje Seaside…

  21. tu było narzekanie na textile :>

  22. do S:
    Z dynamizmem autorowi chodziło o modyfikowanie gotowych klas „on the fly” (nie lubię polskiego „w locie”). Użył przykładu z funkcją odd? i klasą Integer (która jest typem wbudowanym Rubiego.

    Ruby pozwala modyfikować klasy swoje własne bazowe (ale i także stworzone przez użytkownika) w trakcie tworzenia aplikacji.

    puts 5.odd? 
    #test.rb:15: undefined method `odd?' for 5:Fixnum (NoMethodError)
    class Integer  
      def odd?  
        (self % 2) == 1  
      end  
    end  
    puts 5.odd?       # true  
    puts 6.odd?       # false  
    puts 7.odd?       # true  
    

    Teraz chyba jaśniej. ;-)

  23. RaVbaker, a :)

    btw, możliwość dodania metody nie wydaje mi się jakimś cudem na kiju ;> a można dodawać sloty do istniejącej klasy (z automatycznym apgrejdem już istniejących instancji tejże) ? Czy ten automatyczny apgrejd, jeśli jest, można dodatkowo oprogramować ?

  24. Pozwól, że podrzucę Ci kod źródłowy… Wydaje mi się, że właśnie tego oczekujesz… (kod pochodzi z szybko skleconej klasy w IRB)

    irb(main):001:0> class Test
    irb(main):002:1>  def initialize(to)
    irb(main):003:2>   @name = to
    irb(main):004:2>  end
    irb(main):005:1>  attr_accessor :name
    irb(main):006:1> end
    => nil
    irb(main):007:0> t1 = Test.new("t")
    => #<Test:0xb7cd0824 @name="t">
    irb(main):008:0> t1.name
    => "t"
    irb(main):009:0> class Test
    irb(main):010:1>  def func(x)
    irb(main):011:2>   @name = x
    irb(main):012:2>   puts ":-)"
    irb(main):013:2>  end
    irb(main):014:1> end
    => nil
    irb(main):015:0> t1.func("t2")
    :-)
    => nil
    irb(main):016:0> t1.name
    => "t2"
    irb(main):017:0>
    

    Więc jak widzisz wszystko działa. :-)

    Wszystko, czyli (gdybyś jednak nie rozumiał kodu)... Tworzymy klasę Test i definiujemy accessor name. Tworzymy obiekt t1 przy pomocy naszego konstruktora z wartością name=„t”. Potem dopisujemy do klasy Test nową funkcję func. Uruchamiamy ją z parametrem „t2”. A wszystko działa jak powinno. ;-)

    Co rozumiesz przez „dodatkowo oprogramować” ?

  25. RaVbaker, nie o to mi chodziło, ale już sobie sprawdziłem że działa.

    > class Test
    >   def initialize(a)
    >    @a = a
    >   end
    >   attr_accessor :a
    > end
    => nil
    > t = Test.new(1)
    => #<Test:0xb7c08070 @a=1>
    > t.a
    => 1
    > class Test
    >   def initialize(a, b)
    >    @a = a
    >    @b = b
    >   end
    >   attr_accessor :a, :b
    > end
    => nil
    > t.a
    => 1
    t.b
    => nil
    

    Chodziło mi o to czy można jakoś zadeklarować że w momencie w którym Ruby „za plecami” apgrejduje obiekt ma być wykonany dodatkowy kod (tego akurat wciąż nie wiem, ale sobie poczytam).

  26. Tak, Ruby oferuje taką możliwość:

    class Integer  
      def Integer.method_added(name)
        puts "O, nowa metoda: #{name}"
      end
      def odd?  
        (self % 2) == 1  
      end  
    end  
    
    puts 5.odd?
    puts 6.odd?
    

    Kiedy uruchomimy program, najpierw dowiemy się o dodaniu nowej metody, a dopiero potem o nieparzystości tych dwóch liczb. :)

    Określa się to jako „definition hook”. Przyznam, że nie wiem jak nazywa się to w polskiej literaturze.

  27. A co do uciążliwego kopiowania kodu – obecna forma tego bloga jest przejściowa, będzie nowy szablon i przy okazji postaram się nieco usprawnić skrypt od formatowania składni.

  28. Ruby - przegląd języka dla niewtajemniczonych

    W poprzednich dwóch wpisach starałem się przybliżyć Wam kilka, mniej lub bardziej ciekawych faktów na temat Rubiego. Tym razem chciałbym pokazać te jego cechy, które sprawiły, że każdy dotąd poznany przeze mnie język został zepchany[.[...]

  29. Ruby - przegląd języka dla niewtajemniczonych

    W poprzednich dwóch wpisach starałem się przybliżyć Wam kilka, mniej lub bardziej ciekawych faktów na temat Rubiego. Tym razem chciałbym pokazać te jego cechy, które sprawiły, że każdy dotąd poznany przeze mnie język został zepchany[.[...]

  30. ruby to taka odskocznia od rzeczywistosci, jesli nudza wam sie ograniczenia w liczeniu liczb, to popatrzcie sobie na wynik dzalania 2*50000 w kilka milisekund,

    ogolnie jesli cos mam robic dla siebie tak na szybko, to ruby wygrywa z wszystkimi innymi jezykami

    polecam

Dodaj komentarz na temat

Zanim skomentujesz...

W komentarzach działają znaczniki Textile.
Zastrzegam sobie prawo do edycji Twojego komentarza tylko i wyłącznie w celach estetycznych (naprawienie źle wstawionego kodu, itp). Nie zmieniam ich treści, ortografii, interpunkcji. Jeśli odczuwasz potrzebę edycji swojego komentarza, skontaktuj się ze mną, a zdziałamy co trzeba.