Ruby (język programowania)

Z Wikipedii, wolnej encyklopedii
Skocz do: nawigacja, szukaj
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; 26 dni 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]