2007.09_Ruby_[Programowanie].pdf
(
833 KB
)
Pobierz
439031367 UNPDF
dla programistów
Ruby
Ruby
Tomasz Gajewski
Ruby (czyt. Rubi) to nowy język programowania rodem z Japonii. No, może nie taki nowy, bo autor
– Yukihiro „Matz” Matsumoto, zaczął go pisać już ponad 10 lat temu. Przez długi czas rozwijany był
jako projekt opensource tylko przez pasjonatów z Japonii i dlatego pozostawał nierozpoznawalny w
szerszych kręgach.
buje jeszcze jednego języka? Matsumto, ja-
ko administrator Linuksa, marzył o języku
skryptowym, który wspierałby pełną obiek-
towość. Pisanie skryptów – krótkich programików, naj-
częściej jednorazowego użytku, w Javie czy C# jest mało
efektywne. Matsumoto miał ponadto wizję co do sposobu
programowania, która uczyniła Ruby wyjątkowym, któ-
ra swoją oryginalnością zauroczyła rzesze programistów.
Dzięki odrobinie szczęścia (wyjaśnię to za chwilę) Ruby
stał się językiem do pisania nie tylko skryptów, ale i więk-
szych aplikacji biznesowych.
Dave Thomas, autor „Pragmatycznego Programisty”
i wielu innych ciekawych książek, jest gorącym zwolenni-
kiem nauki możliwie wielu języków programowania. Nie
dlatego żeby pisać aplikacje dla klienta, ale dlatego żeby
ustawicznie rozszerzać swój sposób myślenia, jak efektyw-
niej rzeczy mogą być kodowane.
„
Język, który nie zmienia Twojego myślenia o programowa-
niu, nie jest wart nauki
” (Alan Peris)
Ruby idealnie wkomponowuje się w tą wizję. Dlate-
go Dave Thomas, razem z całym swoim wydawnictwem
pragmaticprogrammer.com zaangażowali się w jego pro-
mocję. To dzięki niemu Ruby przekroczył granice Japonii i
opanował resztę świata.
Język skryptowy – bez kontroli typu da-
nych, do pisania prawdziwych programów
Tak, Ruby, podobnie jak większość języków skryptowych,
nie posiada kontroli typu danych (ang.
weekly typed
). Jest
też dynamiczny, co oznacza że kompilowany dopiero w
trakcie wykonania.
Miałem pisać o tym na samym końcu, ale boję się że
wielu czytelników doświadczonych w
PERLu
czy zwłasz-
cza PHP nie dotrze tam. Zbyt wiele niemiłych wspomnień
w ich głowach, aby zaczynać drogę raz jeszcze z niekom-
pilowanym językiem.
PHP też wydawał się kiedyś idealny do pisania apli-
kacji web'owych. Przy odpowiedniej skali wielkości
projektu szybko nim przestawał być. Brak kontroli ty-
pów powodował znacznie większą ilość błędów aniże-
li w aplikacjach Java/C#. To był dobry język „jednooso-
bowy” – jedna osoba panuje nad nim, rozumie co jest
wewnątrz. Ale kilka osób nie jest w stanie pracować w
56
wrzesień 2007
D
laczego powstał Ruby? Czy świat potrze-
dla programistów
Ruby
Listing 1.
Deinicja metody Listing
Listing 4.
Konsola interaktywnej pracy z Ruby
def
will_you_marry_me
(
she
)
expectations
=
she.ind_
expectation
(
expectations
<
my_savings
)
end
Irb
(
main
)
:
001
:
0
>
puts
"Hello Ruby"
Hello Ruby
=>
nil
irb
(
main
)
:
002
:
0
>
100.
times
{
puts
"I love you"
}
I love you
I love you
...
I love you
=>
100
Listing 2.
Równoważne warunki if
if
expectations
<
my_savings
huraaaa
end
huraaaa
if
expectations
<
my_
savings
huraaaa
unless
expectations
>
my_savings
bre). Piszą więc krótkie metody (jak refakto-
ryzacja zaleca) i od razu krótkie testy do nich.
Dzięki temu kod jest programowo testowal-
ny, luźno powiązany i bardziej czytelny. To
niewiarygodnie skuteczna metoda, która za-
wsze wygra z aplikacjami testowanymi ręcz-
nie, ale w językach kompilowalnych.
W obszarze testów jednostkowych Ru-
by jest prawdziwym liderem – nigdzie nie są
lepiej wspierane.
Ruby On Rails
, framework
do pisania aplikacji internetowych, na tyle
mocno je zintegrował, iż potrzeba dużo wy-
siłku aby je zignorować lub, o zgrozo, usu-
nąć. Tu jest ta zasadnicza różnica – inni da-
ją opcję dołączenia testów, Ruby daję opcję
wyłączenia.
Jeśli więc wciąż nie stosujesz TFD, naucz
się Ruby i pozostań przy skryptowaniu. Nie
pisz jednak nic dużego dla klienta – najpraw-
dopodobniej sobie i innym przysporzysz kło-
potów.
tekstowy. Jak szybko i skutecznie wyrazić
miłość? W Ruby nawet to jest możliwe:
100.times { puts "I love you"}
jednym projekcie jednocześnie, bez wyso-
kiej kultury (świadomości) pisania aplika-
cji w zespole.
Niektórzy zarzucą mi, że obecnie najpo-
pularniejszy CMS - Joomla, napisany jest w
PHP. To prawda. Ale jego popularność wyni-
ka głównie z architektury – Ty pisz tylko ma-
łe niezależne od siebie komponenty, a ich po-
łączenie zostaw nam. Inaczej mówiąc – koduj
co chcesz, tylko nic wielkiego.
Czy Ruby może być lepszy pod tym
względem? Przecież też jest niekompilowa-
ny, jak PHP. Na początku powiedziałem że
Ruby miał odrobinę szczęścia i można w nim
kodować większe aplikacje. To szczęście na-
zywa się „odpowiedni czas i miejsce”. A do-
kładniej mówiąc – Testy jednostkowe i Refak-
toryzacja, które upowszechniły się stosunko-
wo niedawno.
Programiści, którzy opanowali praktykę
Test First Development
(TFD), czyli pisania te-
stów w trakcie kodowania (a nie kiedyś tam
po, jak wystarczy czasu) przyzwyczaili się, że
nie muszą „ręcznie” oceniać swoich wyni-
ków pracy, tzn. klikając coś tam i obserwując
czy mniej więcej działa. Dla nich kompilacja
też nie jest potrzebna. Jedyne co jest dla nich
wiarygodne, to wynik zakończenia testów. I
oczywiście obszar kodu, jaki pokryty został
testami (80% to idealny stan, ale i 50% jest do-
Semantyka jest wyrazista; syntaktyka stanie
zrozumiała w trakcie dalszego czytania.
Na Listingu 4 przedstawiono wynik ich
wykonania z konsoli irb (skrót od ang.
interac-
tive ruby
), pozwalającej wykonywać komendy
Ruby w trybie konwersacji (komenda – odpo-
wiedź). Teraz czas na coś bardziej skompliko-
wanego. Stworzymy pierwszą metodę. W Ru-
by możemy deiniować je bez klasy.
Jak widać, linie nie kończą się żadnym
średnikiem. Nie jest to potrzebne, dopóki in-
strukcje separowane są osobnymi liniami. Me-
toda jest pytaniem, więc powinna zwracać wy-
nik. Gdzie jest wynik? W Ruby jest to rezultat
ostatniej wykonanej instrukcji. Można co praw-
da ostatnią instrukcję poprzedzić słowem
re-
turn
, ale to niekonieczne. Podobnie jak PERL,
Ruby chce być blisko języka mówionego i do-
puszcza dowolność budowania zdań. Każde ze
zdań przedstawionych na Listingu 2 jest rów-
noważne: Aby być jeszcze bliżej języka mówio-
nego, pozwala się na dowolność używania na-
wiasów () przy wywoływaniu metod. Każdy z
poniższych sposobów jest akceptowalny:
Hello Ruby
Czas w końcu zobaczyć Ruby w praktyce.
Na początku wypada się przywitać. Pamięta-
cie, ile zachodu potrzeba było w Javie czy C#,
aby wykonać tak prostą rzecz? Jaki przerost
formy nad treścią? Deiniowanie klasy, meto-
dy statycznej
main
etc.? Ruby to język dla bar-
dziej zdecydowanych – proste rzeczy wyko-
nujemy bez namysłu:
will_you_marry_me(Joanne)
will_you_marry_me Joanne
puts "Hello Ruby"
Wyrażenia regularne
W języku skryptowym nie może oczywi-
ście zabraknąć operacji na tekstach. Do
Puts jest metodą wypisująca tekst na ekran.
Między apostrofami umieszczamy literał
Listing 3.
Przykłady operacji na tekstach
" Tom "
.trim
>>
"Tom"
# obetnij spacje z przodu i tyłu
" I like you much"
.squeeze
>>
"I like you much"
# zamień wielokrotne spacje na pojedyncze
"man"
.pluralize
>>
"people"
# liczba mnoga słówka "man"
"apple banna orange"
.split
>>
[
apple
,
banana
,
orange
]
# podziel na osobne wyrazy
www.lpmagazine.org
57
dla programistów
Ruby
Listing 5.
Przykład deinicji i użycia prostej klasy
silibyśmy się do nich używając kolejno
$2
,
$3
... etc. Są to jedne z wielu predeiniowanych
zmiennych, ustawianych zależnie od kontek-
stu. Gdy nasze umiejętności rosną, używamy
ich coraz częściej.
do zmiennych instancji odwołać się później
w kodzie, musimy stworzyć dla nich opako-
wania, powszechniej znane jako metody
set
,
get
. Opakowania get tworzymy wywołując
specjalną metodę
attr_reader
, a
'set'
po-
przez
attr_writer
.
Class
Man
attr_reader
:
name
,
:
age
def
initialize
(
name
,
age
)
@name
,
@age
=
name
,
age
end
end
man
=
Man.new
(
"Tom"
,
20
)
Szybka podmiana
Wieczór rozdania nagród bliski i znów ko-
lejna komplikacja – dwójka aktorów nie da-
rzy się zbytnią sympatią, a my posadziliśmy
ich obok siebie. Jednego z nich trzeba szybko
przesadzić. Jak? W każdym innym języku po-
trzebne jest aby na sale wniesiono dodatkowe
"krzesło tymczasowe". W Ruby przebiega to
trochę sprawniej:
puts man.name
puts "I am adult" unless (man.age <
18)
dyspozycji ma bogatą bibliotekę, jak na
przykład:
Dużo ciekawsze są jednak funkcje, któ-
re przyjmują wyrażenia regularne jako pa-
rametr.
Załóżmy że jesteśmy organizatorem aka-
demii rozdania Oscarów, i mamy już przygo-
towane, niewydrukowane zaproszenia. Po
bliższym przyjrzeniu zauważyliśmy, że data
rozpoczęcia gali jest czasami nieprawidłowa.
Musimy to poprawić.
Wprawni programiści zauważyli pewien
detal – operator new pojawia się za nazwą
klasy a nie przed. Wygląda jak nazwa meto-
dy statycznej, a nie specjalne słowo kluczo-
we języka. I tak w rzeczywistości jest – nie
zdeiniowaliśmy w istocie klasy, a tylko
stałą posiadającą metodę new. Tutaj docho-
dzimy do najciekawszej własności. W Ru-
by wszystko jest obiektem. I to nie tak jak
w Javie, gdzie wszystko było klasą, z drob-
nymi wyjątkami (np: typy prymitywne). W
Ruby nie ma wyjątków – literały liczbowe
są obiektem, nawet nil jest obiektem. Ozna-
cza to możliwość wykonywania metod bez-
pośrednio na nich.
Niestety, obiekt tutaj różni się trochę od
znanych nam dotychczas obiektów z Java
czy C#. Nie ma klasy przypisanej jako typ
– nie wykorzystuje się operatorów (
instan-
ceof
etc.) do sprawdzania typu. Zamiast za-
stosowano podejście
ducktyping
, czyli je-
śli obiekt chodzi jak kaczka, i odpowiada
jak kaczka to prawdopodobnie jest to kacz-
ka. Kluczową w takim podejściu jest metoda
respond_to?
, zwracająca wynik posiadania
metody przez obiekt.
W
ducktyping
sprawdza się więc, czy
obiekt zawiera metody, a nie jakiego jest ty-
pu. Trochę jak w życiu – dla niektórych bar-
dziej liczą się umiejętności niż dyplom. Trud-
no powiedzieć którzy maja rację.
Sam fakt posiadania metody nie jest
oczywiście wystarczający aby jej użyć – na-
leży znać również listę parametrów. Jak to
zrobić? W Ruby nie ma przeciążania metod
więc jedna powinna być dobra dla wszyst-
kich. Zaprawieni w
ducktyping
programi-
ści zadają sobie więc pytanie, co się stanie
gdy do metody przekazana zostanie np. li-
actor_place, other_guy_place = other_
guy_place, actor_place
Jednocześnie możemy więc zwracać wy-
nik do kilku zmiennych. Oczywiście w ten
sam sposób moglibyśmy przesadzić i więcej
uczestników gali na raz.
Spójrzmy jeszcze raz na przykład z po-
przedniego akapitu, na metodę split, rozdzie-
lającą owoce po spacjach:
invitation_text.sub(/\dd-\dd\-d\dd\d/
, "10-10-2007")
W Ruby wyrażenia tworzymy albo z pomo-
cą klasy
RegExp
, albo w wersji szybszej, we-
wnątrz backslashów
/../
.
W powyższym przykładzie podmienia-
my tylko pierwszy tekst pasujący do wyra-
żenia regularnego. Gdybyśmy chcieli zamie-
nić wszystkie wystąpienia, należy użyć me-
tody
gsub
.
Spójrzmy teraz na trochę trudniejszy
przypadek. Dostajemy informację, że w
tym roku pojawi się dwójka gości honoro-
wych i należy im przyznać miejsca o nume-
rach 1, 2. Musimy więc wszystkich pozosta-
łych przesunąć o 2 miejsca. Skorzystamy w
tym celu z grupowania w wyrażeniach re-
gularnych:
"apple banna orange".split =>
["apple", "banana", "orange"]
Aby pobrać tylko pierwsze dwa owoce, za-
miast wszystkich, napiszemy następująco
fruit1, fruit2 = "apple banna
orange".split
Co by się stało, gdyby metoda zwróciła tylko
jeden owoc?
fruit2
otrzymałby wartość
nil
.
Wszystko jest obiektem
Ruby jest językiem obiektowo zorientowa-
nym. Nie jest to „dostawka”, jak w PERLu
czy PHPie, ale obiektowość jest wbudowana
od samego początku. Na Listingu 5 zdeinio-
waliśmy klasę z domyślnym konstruktorem
dwuparametrowym. Symbol
@
daje sygnał,
aby odwołać się do zmiennych instancji kla-
sy, a jeśli takich nie ma – to utworzyć je. Stwo-
rzyliśmy więc dwie zmienne instancji i prze-
pisaliśmy do nich wartości parametrów. Aby
invitation_text.gsub(/Place: (\d*)/,
"Place: #{$1+2}")
Magiczny symbol
$1
oznacza treść tekstu pa-
sującego do wyrażenia ujętego w nawiasach
(). Gdybyśmy mieli więcej nawiasów, odno-
Listing 6.
Wszystko jest obiektem
"Apple"
.downcase
>>
"apple"
# przekształć do małych liter
100.
times
{
..
}
# wykonaj 100 razy blok (w dalszej części poznamy bloki)
nil.methods
# zwróć listę metod należących do obiektu
1
..
5.
each
{
..
}
# wykonaj blok 5 razy
will_you_marry_me.methods # zwróć listę metod należących
do
....
metody
!
58
wrzesień 2007
dla programistów
Ruby
sta zamiast pojedynczej wartości. I kodu-
ją tak, aby metoda potraiła obsłużyć każdą
ewentualność.
„
Hmm, ciekawe. Ale wciąż nie rozumie dla-
czego nie możemy skorzystać ze sprawdzania kla-
sy obiektu?
”. W Ruby istnieje nawet metoda
pozwalająca to zrobić –
kind_of?
. W polskim
tłumaczeniu – „jakiś taki”, co też trafnie od-
powiada na to pytanie. Słowo klasa występu-
je tu bowiem bardziej jako oznaczenie zbioru
metod wyjściowych, niż coś, na czym może-
my polegać. Dzieje się tak dlatego, bo w trak-
cie działania aplikacji możemy obiekt dowol-
nie modelować, dodając nowe metody i mo-
dyikując istniejące. Możemy to czynić za-
równo dla pojedynczych obiektów jak i ca-
łych klas.
Możemy również skorzystać z
MixIn
,
czyli dołączanych do klasy całych modu-
łów metod. Czasami wielu na raz. W Javie
nie ma wielodziedziczenia, ale jest imple-
mentacja wielu interfejsów na raz. Pustych
interfejsów.
Moduły pozwalają osiągnąć podob-
ną funkcjonalność – są jak interfejsy, z w
tym wyjątkiem, że częściowo wypełnione.
Naszym obowiązkiem jest dopisane tylko
jednej – dwóch kluczowych metod, a po-
zostałe dostajemy „za darmo”. Weźmy ja-
ko przykład moduł
Comparable
– zawie-
ra 6 gotowych metod, a brakuje tylko jed-
nej, aby mogły zostać użyte – nierówności
obiektów
<=>
.
Generalnie,
MixIn
przypominają trochę
wzorzec projektowy
Template
– metody w
klasie bazowej polegają na implementacjach
metod abstrakcyjnych w klasach wywiedzio-
nych. Jeszcze ogólniej,
MixIn
przypominają
również... wielodziedziczenie!
• Wszystko co zaczyna się z wielkiej litery,
jest stałą:
• SOME_CONSTANTS
• OtherConstants
• Klasa, jak powiedzieliśmy, też jest stałą
– musi więc zaczynać się z dużej litery.
• Metody w klasie nie są natomiast stały-
mi, dlatego zawsze zaczynają się z małej
litery.
• Do zmiennych instancji odwołujemy się
poprzez symbol @, a do zmiennych glo-
balnych – $
• @instance_variables
• @@class_variables
• $global_variables
• Metody tylko odpytujące obiekt powin-
niśmy kończyć znakiem ?, a metody
zmieniające obiekt – znakiem !.
{ |param1, param2 | puts "Params
values are: #{param1}, #{param2}"}
Spójrzmy teraz w jaki sposób możemy bez-
piecznie z pomocą bloku operować na pli-
kach.
File.open("message.txt") { |ile|
ile.print_lines }
Co tu się stało? Do metody statycznej open
przekazaliśmy blok kodu. W nim zawarli-
śmy wszystko, co chcemy wykonać na pli-
ku. Sama metoda open zatroszczyła się na-
tomiast o detale, jak otwarcie pliku, wyko-
nanie bloku i kolejno zamknięcie. Imple-
mentację open przedstawiono na Listin-
gu 11.
Konstrukcja
begin ... ensure ...
end
to znane z Java/C#
try ... inally
.
Yield natomiast wykonuje przekazany blok,
o ile tylko został przekazany – sprawdza to
block_given
?.
W taki oto sposób myślałem o blo-
kach: użyteczne tylko do obsługi plików,
połączeń z bazą danych, czyli wszędzie
tam, gdzie zasoby muszą zostać zwolnio-
ne. To jednak nieprawda. Blok kryje w so-
bie znacznie więcej. W połączeniu z itera-
torami zmieniają sposób, w jaki dotychczas
zwykliśmy budować pętle. Aby to jednak
zobaczyć, najpierw musimy poznać kon-
tenery.
Martin Fowler pisze [9], że wszystkie metody
w systemie powinny być wyraźnie podzielone
na dwie kategorie: odpytujące i modyikują-
ce. Jeśli metoda zawiera w sobie kalkulację/
logikę (odpytywanie) i modyikacje, to powin-
na zostać zrefaktoryzowana do dwóch metod.
Dlaczego? Bo metody odpytujące bezpiecznie
używać – przecież nic nie modyikują! Dodat-
kowo możemy czynić to w dowolnej kolejno-
ści. Tego samego nie można powiedzieć o me-
todach modyikujących, zwłaszcza kiedy wy-
wołują poniżej kolejne podobne sobie meto-
dy. Każda z nich musi być osobno zanalizo-
wana. No i dowolność wywołania to czyste
szaleństwo. Spójrzmy jeszcze raz na metodę
will_you_marry_me
z początku i poprawmy
ją, aby pasowała do konwencji. Metoda zde-
cydowanie niczego nie zmienia, więc powin-
na kończyć się znakiem zapytania.
Druga metoda, która teraz dodaliśmy
–
get_married_with!
z pewnością niesie
za sobą modyikacje. I niemałe konsekwen-
cje. Byłoby nie fair, gdybyśmy nie ostrzegli
wykrzyknikiem przed jej użyciem.
Listing 7.
Ducktyping – czy metoda odpowiada
if
obiekt.respond_to?
(
sing
)
#to zaśpiewaj
obiekt.sing
end
Konwencje
Jestem pewien, że niektórzy mają już na-
prawdę dosyć. Zmiany pojedynczych obiek-
tów, dowolność wykonywania operatorów,
zmiany istniejących klas,
quasi
wielodziedzi-
czenie! Wszyscy mogą robić wszystko. Jak z
tym żyć?!
Są miejsca, gdzie można na wiele sobie
pozwolić. Ale są i takie, gdzie Ruby jest re-
strykcyjny bardziej niż jakikolwiek inny ję-
zyk. Są to konwencje nazewnicze. Bardzo je
lubię, bo we wszystkich dotychczasowych
projektach, w jakich uczestniczyłem, wpro-
wadzenie konwencji nigdy się całkowicie
nie powiodło. Zawsze ktoś miał „istotny”
powód, aby ich nie stosować. Fakt, sam Ru-
by nie ma ich jeszcze tak wiele, jak np. czyni
to
Ruby On Rails
, ale i tak więcej niż pozosta-
li. Najważniejsze konwencje to:
Listing 8.
Dynamiczne dodawanie metody do
pojedynczego obiektu
Bloki – nigdy więcej zamykania
plików
Ruby wprowadza pojęcie bloków, czyli ka-
wałka kodu, który może być przekazany jako
parametr. No bo i dlaczego nie?!
Blok budujemy na dwa sposoby: krótki
blok jednoliniowy zamykamy w nawiasach
klamrowych
class
<<
obiekt
def
sing
end
end
Listing 9.
Dynamiczne dodawanie metody do
klasy
{ puts "Hello" }
a wieloliniowy blok z pomocą słów
do ...
end
(Listing 12).
Do bloku możemy przekazywać parame-
try, jak do zwykłej funkcji.
class
<<
String
def
sing
end
end
www.lpmagazine.org
59
dla programistów
Ruby
Listing 10.
Podział na metody odpytujące i mo-
dyikujące
fruits = ['apple', 'orange', 'bannan']
fruits.each {|fruit| puts "I am
#{fruit}"}
Listing 11.
Źródło metody open
class
Man
def
will_you_mary_me
?
(
she
)
end
def
get_married_with
!
(
she
)
end
end
Co zrobiliśmy? Na każdym elemencie z ta-
blicy wykonaliśmy blok, wypisujący nazwę
owocu na ekran.
A oto dwa powyższe przykłady z Ha-
skell, przepisane do Ruby:
Def
File
.open
(
*args
)
result
=
f
=
File.new
(
*
args
)
if
block_given?
Begin
result
=
yield
f
ensure
f.close
end
end
return
result
end
Kontenery
Kontenery to nic innego jak zwykle listy i
hash-listy
. Listy budujemy z pomocą nawia-
sów kwadratowych []
[1, 2, 3, 4].map {|i| i+1} =>
[1,2,3,4]
[-1,2,-3,5].select {|i| i>0} =>
[2,5]
I na sam koniec coś trudniejszego
XML'a – dla wygody i szybkości implementa-
cji. Oni i wielu innych programistów.
Cechą narzędzi napisanych w Ruby jest
właściwie całkowity brak plików XML. Po
części wynika to z zastąpienia go Yaml'em,
ale Yaml nie jest używany do konigurowa-
nia. Dlaczego tak się dzieje? Dlaczego nie ma
XMLa? Bo Ruby jest na tyle dynamicznym ję-
zykiem, że wszystkie DSLe łatwiej budować
w samym Ruby, niż uciekać się do XMLa. Jest
jakby połową drogi między prawdziwym par-
serem a nieelastyczną Javą/C#. Spójrzmy na
Listing 13. – porównanie prostego przykładu
ANTa i jego odpowiednika w Ruby – Rake'a.
Kto czytał uważnie ten artykuł, zauwa-
ży że przykład z Rake'a to zwykła składnia
Ruby – jest to wywołanie metody
task
, do
fruits = ['apple', 'orange', 'bannan']
[ 1, 2, 3, 4, 5 ].inject (0) {|v,n|
v+n } => 15
a
hash-listy
z pomocą nawiasów klamrowych
{}
, lub bez.
Jest to zsumowanie wszystkich elementów.
W zmiennej v trzymamy wynik, „wstrzyku-
jąc” mu na początek 0, a do zmiennej n prze-
kazujemy kolejne elementy z listy.
Im więcej pracujemy w Ruby, tym co-
raz częściej korzystamy z takiej kombinacji.
W pewnym momencie zauważamy, że w na-
szym kodzie nie ma prawie pętli
while
i
for
.
Przypomina to trochę sytuację z refaktory-
zacji, gdzie na brak zrozumienia polimori-
zmu wskazywano nadużywanie w kodzie
if
i
switch
. Tutaj takim wyznacznikiem braku
zrozumienia myślenia w Ruby, będzie nad-
używanie właśnie instrukcji
while
i
for
.
fruits = {'a' => 'apple', 'o' =>
orange , 'b' => 'bannan'}
fruits = 'a' => 'apple', 'o' => orange
, 'b' => 'bannan'
Same kontenery oczywiście nie wnoszą
nic nowego – spotykamy je w każdym ję-
zyku obiektowym.
To co jest interesujące,
to sposób ich używania, albo raczej nad-
używania.
Języki funkcyjne, takie jak Haskell, ma-
ją tą własność, że rzadko operują na poje-
dynczych wartościach. Funkcje matematycz-
ne (operacje) stosuje się na całych listach, a
wynikiem jest zwykle nowa lista. Spójrzmy
na przykład:
DSL
Być może część czytelników już usłyszała
gdzieś ten skrót, ale duża część na pewno
jeszcze nie. Uprzedzam, że nie mam na my-
śli modelu modemu. DSL to skrót od
Doma-
in Speciic Language
czyli język specyiczny w
danej domenie zastosowania. A konkretniej?
Język, który ma bardzo wąskie zastosowanie.
Takim językiem jest np. ANT – jego instrukcje
służą zasadniczo tylko do kompilacji. Dzięki
temu ograniczeniu czytając plik ANT operu-
jemy na dużo wyższym poziomie abstrakcji,
niż gdybyśmy musieli czytać te same instruk-
cje napisane w Java.
Ok – widzę jak wielu się śmieje. XML?
Język programowania? Co to za język?! Ma-
ją rację! Ironią losu jest jednak, że programu-
jąc w Java, więcej czasu konigurujemy coś w
XML niż piszemy w samej Javie. A dlaczego
wszystkie koniguracje są w XML? Bo napi-
sanie parsera do własnego języka DSL jest
wciąż bardzo trudne (można to uczynić np.
w ANTLR) i niewielu programistów to potra-
i. Tylko z tego względu autorzy ANT'a użyli
map (+) 1 [0,1,2,3] => [1,2,3,4] #
dla każdego elementu z listy stosujemy funk-
cję zwiększenia o 1.
Albo inny:
ilter (>) 0 [-1, 2, -3, 5] => [2,5] #
z listy wybieramy tylko elementy większe
od zera.
Jeśli spojrzymy na listę metod dowolne-
go kontenera w Ruby, wśród wyników znaj-
dziemy zadziwiająco podobne funkcje:
each
,
map
,
select
,
collect
etc. Są to tzw. iterato-
ry. Czy Ruby to język funkcyjny? Jeszcze nie.
Wydaje się być w połowie drogi.
for, while – a co to?
Zobaczmy w końcu, jak „złota trójka” czyli
kontenery, iteratory i bloki pracują razem.
Rysunek 1.
Programowanie ducktyping, czyli wszyst-
ko, co porusza się i mówi jak kaczka, jest kaczką
60
wrzesień 2007
Plik z chomika:
SOLARIX33
Inne pliki z tego folderu:
2006.01_Koder plików w formacie OGG_[Programowanie].pdf
(722 KB)
2007.06_Piękno fraktali_[Programowanie].pdf
(1778 KB)
2008.11_GanttProject_[Programowanie].pdf
(1014 KB)
2007.04_USB Device Explorer_[Programowanie].pdf
(1134 KB)
2006.09_QT, PyQT – szybkie tworzenie baz danych_[Programowanie].pdf
(1319 KB)
Inne foldery tego chomika:
Administracja
Aktualnosci
Audio
Bazy Danych
Bezpieczenstwo
Zgłoś jeśli
naruszono regulamin