Ruby (język programowania)
Ten artykuł od 2014-11 zawiera treści, przy których brakuje odnośników do źródeł. |
![]() Logo języka | |
Pojawienie się | |
---|---|
Paradygmat | |
Typowanie | |
Implementacje | Ruby MRI, JRuby, Rubinius, IronRuby, MagLev, MacRuby, RubyMotion, mruby |
Aktualna wersja stabilna | 3.1.3 |
Twórca | |
Licencja | Ruby, GNU GPL |
Platforma sprzętowa | |
Platforma systemowa | |
Strona internetowa |
Ruby (wym. /ˈru:bi/)[1] – 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
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[2]. Kolejne wersje były zwyczajowo wydawane w święta Bożego Narodzenia: 2.1.0 w 2013 roku[3], 2.2.0 w 2014[4], 2.3.0 w 2015[5], 2.4.0 w 2016[6] i 2.5.0 w 2017[7]. Data ta jest nawiązaniem do 25 grudnia 1996, kiedy została wydana wersja 1.0[8].
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[9].
W 2020 roku wydano Ruby 3.0[10]. 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[11]. 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[12][13].
Cechy szczególne
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
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
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”)[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 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[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
Wszystko jest obiektem
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
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
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
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
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
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
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ż
Przypisy
- ↑ dictionary.cambridge.org.
- ↑ Wydanie Ruby 2.0.0. [dostęp 2015-06-09]. (ang.).
- ↑ Ruby 2.1.0 is released, www.ruby-lang.org [dostęp 2018-03-27] .
- ↑ Ruby 2.2.0 Released, www.ruby-lang.org [dostęp 2018-03-27] .
- ↑ Ruby 2.3.0 Released, www.ruby-lang.org [dostęp 2018-03-27] .
- ↑ Ruby 2.4.0 Released, www.ruby-lang.org [dostęp 2018-03-27] .
- ↑ Ruby 2.5.0 Released, www.ruby-lang.org [dostęp 2018-03-27] .
- ↑ The Ruby Community’s Christmas Releases, www.rubyinside.com [dostęp 2018-03-27] (ang.).
- ↑ Ruby 2.6.0-preview1 Released, www.ruby-lang.org [dostęp 2018-03-27] .
- ↑ Ruby 3.0.0 Released, www.ruby-lang.org [dostęp 2021-06-10] (ang.).
- ↑ Ruby 3x3: Matz, Koichi, and Tenderlove on the future of Ruby Performance [dostęp 2018-03-27] (ang.).
- ↑ Olivier Lacan , Concurrency in Ruby 3 with Guilds, „Olivier Lacan”, 27 września 2016 [dostęp 2018-03-27] (ang.).
- ↑ Ractor: Ruby’s Version of the Actor Model | Scout APM Blog, scoutapm.com [dostęp 2021-12-21] .
- ↑ Building a Faster Ruby Garbage Collector. 3-04-2011. [dostęp 2015-05-01].
- ↑ 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)].
- ↑ João Miranda: Ruby 2.2.0 Released, Featuring Incremental and Symbol GC. 29-12-2014. [dostęp 2015-05-01].
- ↑ CRuby, MRI, JRuby, RubySpec, Rubinius, YARV: A Little Bit of Ruby Naming, „Appfolio Engineering” [dostęp 2018-03-27] (ang.).
- ↑ Nick Sieger , Concurrency in JRuby [dostęp 2018-03-27] (ang.).
- ↑ jruby/jruby, GitHub [dostęp 2018-03-27] (ang.).
- ↑ Battle of Interpreters: MRI vs JRuby vs Rubinius, „RubyGuides”, 3 października 2016 [dostęp 2018-03-27] (ang.).
- ↑ Brian Shirai , 5 Things You’ll Love About Rubinius [dostęp 2018-03-27] [zarchiwizowane z adresu 2018-03-28] (ang.).
- ↑ MagLev, maglev.github.io [dostęp 2018-03-27] .
- ↑ oracle/truffleruby, GitHub [dostęp 2018-03-27] (ang.).
- ↑ Very High Performance C Extensions For JRuby+Truffle, chrisseaton.com [dostęp 2018-03-27] .
- ↑ Andrea Singh: Ruby’s Eigenclasses Demystified. 2011-06-24. [dostęp 2015-06-09]. [zarchiwizowane z tego adresu (2015-02-26)]. (ang.).
Linki zewnętrzne
Media użyte na tej stronie
Autor: Yukihiro Matsumoto, Ruby Visual Identity Team, Licencja: CC BY-SA 2.5
Official Ruby logo