Ruby (język programowania)

Z Wikipedii, wolnej encyklopedii
Przejdź do nawigacji Przejdź do wyszukiwania
Ruby
Logo języka
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 2.5.1 / 28 marca 2018; 3 miesiące temu[1]
Twórca Yukihiro Matsumoto
Licencja Ruby, GNU GPL
Platforma sprzętowa wieloplatformowy
Platforma systemowa wieloplatformowy
Strona internetowa

Ruby (wym. /ˈru:bi/)[2]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 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 | edytuj kod]

Yukihiro Matsumoto, twórca Ruby

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.

W roku 2005 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.

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[3]. Kolejne wersje były zwyczajowo wydawane w święta Bożego Narodzenia: 2.1.0 w 2013 roku[4], 2.2.0 w 2014[5], 2.3.0 w 2015[6], 2.4.0 w 2016[7] i 2.5.0 w 2017[8]. Data ta jest nawiązaniem do 25 grudnia 1996, kiedy została wydana wersja 1.0[9].

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

Przyszłość[edytuj | edytuj kod]

W 2020 roku planowane jest wydanie Ruby 3.0[11]. Wersja ta koncentruje się wokół hasła "Ruby 3x3", które oznacza m.in. że wersja 3 ma być trzy razy szybsza od wersji 2.0[12]. Kolejnym znaczącym usprawnieniem ma być wprowadzenie zupełnie nowego modelu współbieżności, opartego o "gildie". Kod wykonywany w obrębie gildii ma być, podobnie jak obecnie, wykonywany z użyciem Global Interpreter Lock, jednak różne gildie mają móc być wykonywane w pełni współbieżnie[13].

Cechy szczególne[edytuj | edytuj kod]

Ruby posiada:

  • automatyczne odśmiecanie pamięci (ang. garbage collection) – 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[14]. W wersji 2.1 wprowadzono nowy generacyjny system odśmiecania pamięci (generational garbage collection), który jednak okazał się niewystarczająco poprawiony[15]. Z tego powodu w wersji 2.2.0 pojawiła się kolejna, inkrementalna, implementacja garbage collectora. Dodano w niej również odśmiecanie symboli, które w poprzednich wersjach nie były nigdy sprzątane[16].
  • 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

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

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.

REPL[edytuj | edytuj kod]

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

Implementacje[edytuj | edytuj kod]

Główna implementacja jeżyka 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")[17]. Istnieją również inne implementacje języka. Wśród nich najistotniejsze to:

  • JRuby – wersja działająca na Wirtualnej maszynie Javy; wspiera, w odróżnieniu od CRuby, pełną współbieżność (bez Global Interpreter Lock)[18] oraz kompatybilność z bibliotekami Javy[19].
  • Rubinius – interpreter Ruby, którego głównym celem jest, by jak największa jego część była napisana w samym Ruby[20] (używając LLVM)[21]. Inne fragmenty napisane są w C++. Rubinius, podobnie jak JRuby, nie posiada GIL i wspiera pełną współbieżność.
  • MagLev – implementacja bazująca 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[22], od tamtej pory jest praktycznie nierozwijana.
  • TruffleRuby – eksperymentalna, skoncentrowana na wydajności, implementacja języka oparta o GraalVM (Oracle)[23]. Jej najważniejszą cechą jest (docelowe) wsparcie dla rozszerzeń pisanych w języku C, a więc dotąd dostępnych wyłącznie w implementacji CRuby[24].

Przykłady[edytuj | edytuj kod]

Wszystko jest obiektem[edytuj | edytuj kod]

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). Ruby posiada również wiele metod introspektywnych, na przykład .class, zwracająca klasę danego obiektu lub .public_methods, zwracająca listę publicznych metod obiektu.

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

1.public_methods.size #=> 130 (może się różnić w zależności od wersji)

Zmienna liczba argumentów funkcji[edytuj | edytuj kod]

W Rubym przekazywanie zmiennej liczby argumentów do funkcji odbywa się następująco: ostatni parametr można zacząć od znaku *, co oznacza, że dowolna liczba parametrów zostanie przekształcona w tablicę. Można też w drugą stronę - tablicę przekształcić w listę argumentów (zarówno dla funkcji o stałej jak i dla funkcji o zmiennej liczbie argumentów) umieszczając znak * na początku:

def reverse_array(*b)
    if b.size == 1
        return b
    else
        return reverse_array(*b[1..-1])+[b[0]]
    end
end

print reverse_array("!\n","ld","wor",", ","llo","He")

Argumenty domyślne[edytuj | edytuj kod]

Argumenty funkcji mogą mieć domyślne wartości. W poniższym przykładzie pierwszy parametr - greeted - ma nadpisaną wartość "world", a drugi - greeting - zostaje z domyślnym "Hello".

def greet(greeted="world",greeting="Hello")
    greeting + ", " + greeted + "!\n"
end

print greet("people")

Wyrażenia lambda[edytuj | edytuj kod]

W Ruby można konstruować anonimowe funkcje za pomocą wyrażeń lambda. Wywołuje się je za pomocą metody call.

add2 = lambda {|x| x+2}  # podstawowy zapis lambdy
add2 = ->(x) { x+2 }     # równoważny zapis przy użyciu "dash-rocket", działa w Ruby od wersji 1.9

add2.call(10)            #=> 12

def addX(x)
    lambda {|y| y+x}
end

add3 = addX(3)
add3.call(10)            #=> 13

Domknięcia[edytuj | edytuj kod]

Każde wyrażenie lambda posiada zasięg leksykalny zakresu, w którym zostało stworzone (tak więc jeśli w bloku domknięcia użyjemy zmiennej lokalnej, będzie ona istnieć do chwili destrukcji samego wyrażenia lambda).

def fun
    a=0     # zmienna lokalna

    lambda{p a+=1} # uchwycenie zmiennej lokalnej w domknięciu
end

f=fun

f.call # 1
f.call # 2

Marshalling[edytuj | edytuj kod]

W Ruby nawet bardzo skomplikowane dane można zrzucić do łańcucha tekstowego, wysłać go lub zachować do pliku, po czym wczytać ponownie. b w poniższym przykładzie to zwykły łańcuch tekstowy.

a=["hello",["world"]]
b=Marshal.dump a
c=Marshal.load b

print a.inspect, "\n"
print c.inspect, "\n"

Metody dodawane do obiektu[edytuj | edytuj kod]

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), która w drzewie hierarchii dziedziczenia znajduje się pomiędzy samym obiektem a jego jawną klasą[25].

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

class Foo
    def greet
        print "Hello, world!\n"
    end
end

x = Foo.new
y = Foo.new

class << y
    def greet
        print "Goodbye, world!\n"
    end
end

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

Zobacz też[edytuj | edytuj kod]

Przypisy[edytuj | edytuj kod]

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

Linki zewnętrzne[edytuj | edytuj kod]