Ruby (język programowania)

język programowania

Ruby (wym. [ˈru:bi]) – interpretowany, w pełni obiektowy i dynamicznie typowany język programowania stworzony w 1995 roku przez Yukihiro Matsumoto (pseudonim Matz). W języku angielskim ruby oznacza rubin.

Ruby
Logo języka Ruby
Logo języka
Pojawienie się

1995

Paradygmat

wieloparadygmatowy

Typowanie

dynamiczne (duck typing)

Implementacje

Ruby MRI, JRuby, Rubinius, IronRuby, MagLev, MacRuby, RubyMotion, mruby

Aktualna wersja stabilna

3.3.0
(25 grudnia 2023) [±]

Twórca

Yukihiro Matsumoto

Licencja

Ruby, GNU GPL

Platforma sprzętowa

wieloplatformowy

Platforma systemowa

wieloplatformowy

Strona internetowa

Ruby bazuje na wielu językach, takich jak CLU, Eiffel, Lisp, Perl, Python czy Smalltalk. Składnia jest zorientowana liniowo i oparta na składni CLU oraz, w mniejszym stopniu, Perla.

Rozwój języka edytuj

 
Yukihiro Matsumoto, twórca Ruby

Pierwsze wydanie Ruby 0.95 zostało ogłoszone w Japonii, 21 grudnia 1995 roku. Już na tym wczesnym stopniu rozwoju języka dostępnych było wiele funkcji, występujących również w późniejszych wydaniach Ruby, wliczając programowanie obiektowe, klasy z dziedziczeniem, iteratory, domknięcie, wyjątki, oraz odśmiecanie pamięci.

Po wydaniu Ruby 0.95 w 1995 roku, zostało wydanych kilka kolejnych stabilnych wersji:

  • Ruby 1.0: grudzień 25, 1996;
  • Ruby 1.2: grudzień 1998;
  • Ruby 1.4: sierpień 1999;
  • Ruby 1.6: wrzesień 2000.

W 2000 roku Ruby stało się popularniejsze od Pythona w Japonii. We wrześniu 2000 roku ukazała się pierwsza książka w języku angielskim o programowaniu w Ruby, co dodatkowo zwiększyło popularność Ruby wśród osób anglojęzycznych.

Od roku 2003 lawinowo zdobywa nowych zwolenników, głównie za sprawą popularnego frameworku do tworzenia aplikacji internetowych o nazwie Ruby on Rails, tworzonego przez grupę programistów pod kierownictwem Davida Heinemeiera Hanssona.

Według statystyk sklepu Amazon.com, dwie najpopularniejsze książki na temat Ruby i Ruby on Rails były najlepiej sprzedawanymi pozycjami z kategorii Programowanie w 2005 roku.

30 stycznia 2009 roku została wydana wersja 1.9.1. Poprawiła ona m.in. obsługę Unicode i wydajność interpretera, dzięki wprowadzeniu nowego mechanizmu o nazwie YARV (ang. Yet Another Ruby VM).

24 lutego 2013 została wydana wersja 2.0.0[1]. Kolejne wersje były zwyczajowo wydawane w święta Bożego Narodzenia: 2.1.0 w 2013 roku[2], 2.2.0 w 2014[3], 2.3.0 w 2015[4], 2.4.0 w 2016[5] i 2.5.0 w 2017[6]. Data ta jest nawiązaniem do 25 grudnia 1996, kiedy została wydana wersja 1.0[7].

W lutym 2018 roku wydana została wersja preview Ruby 2.6, która zawierała m.in. wstępną wersję wsparcia dla kompilacji just-in-time, mającej znacząco przyspieszyć wykonywanie programów w Ruby[8].

W 2020 roku wydano Ruby 3.0[9]. Wersja ta koncentruje się wokół hasła „Ruby 3x3”, które oznacza m.in. że wersja 3 jest trzy razy szybsza od wersji 2.0[10]. Kolejnym znaczącym usprawnieniem jest wprowadzenie zupełnie nowego modelu współbieżności, opartego o „ractory” (pierwotnie mające się nazywać „gildiami”). Kod wykonywany w obrębie ractory jest wykonywany z użyciem Global Interpreter Lock, jednak różne ractory są wykonywane w pełni współbieżnie[11][12].

Cechy edytuj

Ta sekcja jest niekompletna. Jeśli możesz, rozbuduj ją.

Odśmiecanie pamięci edytuj

Ruby posiada automatyczne odśmiecanie pamięci (ang. garbage collection), w związku z czym programiści nie muszą zajmować się ręcznym nią zarządzaniem. W standardowej implementacji MRI w starych wersjach stosowany był wolny garbage collector typu mark-and-sweep, który aby wykonać czyszczenie musiał zatrzymać wykonanie programu (stop-the-world) i był krytykowany za zbyt wolne działania[13]. W wersji 2.1 wprowadzono nowy generacyjny system odśmiecania pamięci (generational garbage collection), który jednak okazał się niewystarczająco poprawiony[14]. Z tego powodu w wersji 2.2.0 pojawiła się inna, inkrementalna, implementacja garbage collectora. Dodano w niej również odśmiecanie symboli, które w poprzednich wersjach nie były nigdy sprzątane[15].

Wszystko jest obiektem edytuj

W języku Ruby wszystko jest obiektem. Oznacza to, że nie ma podziału na obiekty zachowujące się jak obiekt oraz inne (na przykład prymitywy w Javie)[16].

"abc".length   #=> 3
1.to_s         #=> "1"
1.class        #=> Fixnum
Fixnum.class   #=> Class (również klasa jest obiektem)

Singleton class / eigenclass edytuj

W każdym obiekcie metody pochodzące z klasy mogą być nadpisane bez stosowania jawnego dziedziczenia. Wynika to z faktu, że każdy obiekt jest instancją tzw. singleton class (nie mylić z wzorcem projektowym Singleton) lub eigenclass, która w drzewie hierarchii dziedziczenia znajduje się pomiędzy samym obiektem a jego jawną klasą[17].

W poniższym przykładzie metoda greet obiektu y zostaje nadpisana.

class Foo
  def greet
    "Hello, world!"
  end
end

x = Foo.new
y = Foo.new

class << y
  # nadpisanie metody tylko w eigenclass obiektu y
  def greet
    "Goodbye, world!"
  end
end

x.greet
#=> "Hello, world!"
y.greet
#=> "Goodbye, world!"

Przenośność edytuj

Ponieważ Ruby jest językiem interpretowanym, programy pisane w Ruby charakteryzują się wysoką przenośnością pomiędzy platformami (istnieją implementacje na wiele systemów Uniksowych, DOS, Windows, OS X, BeOS itd.).

REPL edytuj

Standardowa dystrybucja Ruby zawiera program IRB (Interactive Ruby Shell), który stanowi REPL dla języka i pozwala na interaktywne eksperymentowanie z jego funkcjami lub bibliotekami. Przykładowa sesja IRB (Ruby 2.1.5):

$ irb
2.1.5 :001 > def double(x)
2.1.5 :002?>   x * 2
2.1.5 :003?>   end
 => :double
2.1.5 :004 > double(3)
 => 6
2.1.5 :005 > double("abc")
 => "abcabc"
2.1.5 :006 > puts "Hello world!"
Hello world!
 => nil

Inne edytuj

  • iteratory
  • przeciążanie operatorów (ang. operator overloading)
  • normalne i zaawansowane właściwości zorientowania obiektowego (klasa, metoda...)
  • obsługa wyjątków (ang. exception handling)
  • wyrażenia regularne wbudowane w składnię
  • liczby całkowite o dowolnych rozmiarach
  • dodawanie metod do instancji klasy – możliwa jest zmiana lub dodanie metody do instancji danej klasy
  • bloki i lambdy (closures) – wygodne przekazywanie funkcji jako parametrów
  • Duck typing” – rozpoznawanie typów na podstawie ich zachowania, a nie deklaracji
  • moduły – rodzaj wielodziedziczenia pozwalający włączyć gotową implementację zbioru metod do danej klasy
  • możliwość zmiany praktycznie wszystkiego – dodanie dodatkowych metod do klasy Array, czy zmiana sposobu drukowania liczb całkowitych są niezmiernie proste.
  • zmienne leksykalne modyfikowalne w czasie działania programu

Składnia edytuj

Składnia Ruby jest podobna do Perl i Python. Definicje klas i metod są sygnalizowane za pomocą słów kluczowych, podczas gdy bloki kodu można definiować zarówno za pomocą słów kluczowych, jak i nawiasów klamrowych. W przeciwieństwie do Perl, zmienne nie muszą obowiązkowo zaczynać się od sygnetu. Jeśli są używane, sygnet zmienia semantykę zasięgu zmiennej. W praktyce nie ma rozróżnienia między wyrażeniami a instrukcjami. Znaczenie ma też podział na linie, gdzie zakończenie linii jest traktowane jako koniec instrukcji, choć równoważnie można używać średnika. W przeciwieństwie do Python, wcięcia nie mają znaczenia.

Jedną z różnic względem Python i Perl jest to, że Ruby przechowuje wszystkie swoje zmienne instancji w pełni jako prywatne dla klasy i udostępnia je tylko poprzez metody dostępowe (attr_writer, attr_reader itp.). W odróżnieniu od "getterów" i "setterów" w innych językach, takich jak C++ czy Java, metody dostępowe w Ruby można utworzyć za pomocą jednej linii kodu poprzez metaprogramowanie. Jednak metody dostępowe można również tworzyć w tradycyjny sposób, jak w C++ czy Java. Wywołanie tych metod nie wymaga użycia nawiasów, więc jest banalnie proste zmienić zmienną instancji na pełną funkcję, bez zmiany ani jednej linii kodu wywołującego, co pozwala uzyskać funkcjonalność podobną do właściwości C# i VB.NET.

Deskryptory własności w Pythonie są podobne, ale wiążą się z pewnym kompromisem w procesie rozwoju. Jeśli zaczniemy w Pythonie od używania publicznie wystawianej zmiennej instancji, a później zmienimy implementację, aby używać prywatnej zmiennej instancji wystawianej poprzez deskryptor właściwości, to kod wewnątrz klasy może wymagać dostosowania do korzystania z prywatnej zmiennej zamiast publicznej właściwości. Projektowanie Ruby wymusza, aby wszystkie zmienne instancji były prywatne, ale jednocześnie dostarcza prosty sposób deklarowania metod dostępowych. Jest to zgodne z ideą, że w Ruby nigdy nie dostępuje się bezpośrednio do wewnętrznych składników klasy z zewnątrz klasy; zamiast tego wysyła się wiadomość do klasy i otrzymuje się odpowiedź.

Licencja edytuj

Ruby jest rozwijany jako otwarte oprogramowanie i dostępny na licencji GPL oraz na własnej licencji wymagającej zmiany nazw plików wykonywalnych w przypadku zamknięcia kodu.

Implementacje edytuj

Główna implementacja języka Ruby, utrzymywana m.in. przez Matsumoto, jest napisana w języku C. Standardową nazwą używaną do jej określania jest CRuby. Można jednak spotkać się ze stosowaniem nazwy MRI („Matz’s Ruby Interpreter”)[18]. Istnieją również inne implementacje języka. Wśród nich najistotniejsze to:

Nierozwijane edytuj

  • MagLev – implementacja bazująca na maszynie wirtualnej GemStone S/3.1 od VMware, koncentrująca się głównie na wydajności. Wersja 1.0 została wydana w 2011 roku[23], od tamtej pory jest praktycznie nierozwijana.
  • Rubinius – interpreter Ruby, którego głównym celem jest, by jak największa jego część była napisana w samym Ruby[24] (używając LLVM)[25]. Inne fragmenty napisane są w C++. Rubinius, podobnie jak JRuby, nie posiada GIL i wspiera pełną współbieżność. Ostatnia wersja (5.0) została wydana w maju 2020 roku[26].

Zobacz też edytuj

  • Ruby on Rails – popularny framework aplikacji webowych, napisany w Ruby

Przypisy edytuj

  1. Wydanie Ruby 2.0.0. [dostęp 2015-06-09]. (ang.).
  2. Ruby 2.1.0 is released, www.ruby-lang.org [dostęp 2018-03-27].
  3. Ruby 2.2.0 Released, www.ruby-lang.org [dostęp 2018-03-27].
  4. Ruby 2.3.0 Released, www.ruby-lang.org [dostęp 2018-03-27].
  5. Ruby 2.4.0 Released, www.ruby-lang.org [dostęp 2018-03-27].
  6. Ruby 2.5.0 Released, www.ruby-lang.org [dostęp 2018-03-27].
  7. The Ruby Community’s Christmas Releases, www.rubyinside.com [dostęp 2018-03-27] (ang.).
  8. Ruby 2.6.0-preview1 Released, www.ruby-lang.org [dostęp 2018-03-27].
  9. Ruby 3.0.0 Released, www.ruby-lang.org [dostęp 2021-06-10] (ang.).
  10. Ruby 3x3: Matz, Koichi, and Tenderlove on the future of Ruby Performance [dostęp 2018-03-27] (ang.).
  11. Olivier Lacan, Concurrency in Ruby 3 with Guilds, „Olivier Lacan”, 27 września 2016 [dostęp 2018-03-27] (ang.).
  12. Ractor: Ruby’s Version of the Actor Model | Scout APM Blog, scoutapm.com [dostęp 2021-12-21].
  13. Building a Faster Ruby Garbage Collector. 3-04-2011. [dostęp 2015-05-01].
  14. Tim Robertson: Ruby Garbage Collection: Still Not Ready for Production. 27-03-2014. [dostęp 2015-05-01]. [zarchiwizowane z tego adresu (2015-08-27)].
  15. João Miranda: Ruby 2.2.0 Released, Featuring Incremental and Symbol GC. 29-12-2014. [dostęp 2015-05-01].
  16. Thomas 2009 ↓, s. 37.
  17. Andrea Singh: Ruby’s Eigenclasses Demystified. 2011-06-24. [dostęp 2015-06-09]. [zarchiwizowane z tego adresu (2015-02-26)]. (ang.).
  18. CRuby, MRI, JRuby, RubySpec, Rubinius, YARV: A Little Bit of Ruby Naming, „Appfolio Engineering” [dostęp 2018-03-27] (ang.).
  19. Nick Sieger, Concurrency in JRuby [dostęp 2018-03-27] (ang.).
  20. jruby/jruby, GitHub [dostęp 2018-03-27] (ang.).
  21. oracle/truffleruby, GitHub [dostęp 2018-03-27] (ang.).
  22. Very High Performance C Extensions For JRuby+Truffle, chrisseaton.com [dostęp 2018-03-27].
  23. MagLev, maglev.github.io [dostęp 2018-03-27].
  24. Battle of Interpreters: MRI vs JRuby vs Rubinius, „RubyGuides”, 3 października 2016 [dostęp 2018-03-27] (ang.).
  25. Brian Shirai, 5 Things You’ll Love About Rubinius [dostęp 2018-03-27] [zarchiwizowane z adresu 2018-03-28] (ang.).
  26. Rubinius: Releases, GitHub [dostęp 2023-09-11] (ang.).

Bibliografia edytuj

  • Dave Thomas, Programming Ruby 1.9. The Pragmatic Programmers’ Guide, 2009, ISBN 1-934356-08-5.

Linki zewnętrzne edytuj