Scala i Maven – część II

W ostatniej części udało się nam stworzyć projekt który świetnie będzie się nadawał do naszych testów jak również zdążyliśmy poznać podstawowe komendy służące do pracy z projektem. Podstawową zaletą naszego rozwiązania jest kompaktowość. W chwili obecnej możemy wybrać czy chcemy na nim pracować w oparciu o Netbeans’a, Eclipse czy choć by Textmate’a.

W tej części chcę przedstawić podstawowe zasady obowiązujące podczas użytkowania interpretera Scali w trybie interaktywnym, jak również podstawy samego języka. Pierwszą rzeczą o której musimy pamiętać to fakt że Scala jest językiem z dwóch światów, programowania obiektowego jak również funkcyjnego. Szczególną uwagę powinniśmy poświęcić na podejście funkcyjne, które stoi u podstaw tego języka, dla którego właściwie sam język powstał.

Podstawową zaletą Scali w procesie jej poznawania że praktycznie od samego początku będziemy mogli zacząć jej adopcje w naszych projektach gdyż możemy jej używać jak zwykłej Javy (oczywiście po uwzględnieniu różnic składni) tak aby z czasem, powiększając nasz zakres wiedzy, przejść do możliwości funkcyjnych, których siłę poznamy przy okazji Wielowątkowości która znacząco się różni od tej którą znamy z Javy.

Czas przejść do czynów, w tym celu uruchamiamy konsole scali za pomocą wcześniej poznanej komendy:

mvn scala:console

W tym momencie powinniśmy po zakończeniu wywołania zobaczyć taki oto komunikat oraz znak gotowości mówiący nam że możemy rozpocząć pracę z konsolą Scali:

Welcome to Scala version 2.7.3.RC2 (Java HotSpot(TM) 64-Bit Server VM, Java ...
Type in expressions to have them evaluated.
Type :help for more information.

scala> _

W tym momencie możemy rozpocząć pracę ze Scalą w trybie interaktywnym. Pierwszym naszym zadaniem będzie zdefiniowanie zmiennej:

scala> val helloWorld = "Hello world!"
helloWorld: java.lang.String = Hello world!

scala> helloWorld = "Second message"
:5: error: reassignment to val
       helloWorld = "Second message"
                  ^

Powinniśmy w tym momencie zwrócić uwage na to że nie użyliśmy ; na końcu lini gdyż w przeciwieństwie do Javy jest on opcjonalny w Scali. W drugim poleceniu chcieliśmy nadpisać wartość naszej zmiennej, nie udało się nam gdyż słowo kluczowe val mówi nam że zmienna ta jest typu immutable, (z punktu widzenia Javy - final) która zresztą stoi u podstaw programowanie funkcyjnego.

W przypadku programowania czysto obiektowego może być ciężko pracować na zmiennych val dlatego możemy użyć var:

scala> var muthelloWorld = "Hello world!"
muthelloWorld: java.lang.String = Hello world!

scala> muthelloWorld = "Second message"
muthelloWorld: java.lang.String = Second message

Jak widzimy wszystko działa zgodnie z naszymi oczekiwaniami. Warto przy tej okazji zwrócić uwagę na to że interpreter informuje nas w trybie interaktywnym o typie zmiennej. Jako że Scala jest językiem ścisłego typowania należy tutaj słowo wyjaśnienia, a mianowicie fakt że Scala podobnie jak C# w ver. 3.0 potrafi samemu odgadywać typ zmiennej na podstawie prawej strony przypisania. Poniżej ten sam przykład z definicją typu:

scala> var muthelloWorld:String = "Hello world!"
muthelloWorld: String = Hello world!

Również tutaj musimy wyjaśnić pewną nieścisłość, w poprzednim przykładzie uzyskaliśmy typ java.lang.String natomiast w obecnym typ String. Typ String został podobnie jak wszystkie typy Scali jest wrapperem który w procesie kompilacji zostanie przetłumaczony na typ java.lang.String.

Warto w tym miejscu wspomnieć że w Scali nie istnieją typy proste, a jedynie obiekty. Wspomniane definicje obiektów jak również definicje użytecznych funkcji języka Scala znajdują się w pliku Predef.scala w bibliotece Scali. Plik ten jest zawsze domyślnie importowany w każdym kodzie w sposób nie jawny.

Jedną z użytecznych funkcji zdefiniowanych w w/w pliku jest println:

scala> println(helloWorld)
Hello world!

Warto tutaj jeszcze wspomnieć o ciekawej właściwości naszego interpretera Scali, mianowicie o automatycznym nazywaniu zmiennych które zdefiniujemy na stosie w sposób anonimowy:

scala> "new message from space"
res3: java.lang.String = "new message from space"

W tym momencie widzimy że została automatycznie wygenerowana nazwa zmiennej res3 którą zresztą możemy w każdej chwili wykorzystać:

scala> println(res3)
new message from space

Przyszła teraz kolej na zdefiniowanie naszej pierwszej funkcji, robimy to w sposób następujący z użyciem słowa kluczowego def:

scala> def fun() { println("fun") }
fun: ()Unit

Proszę zwrócić uwagę na typ zwracany przez naszą funkcje Unit, w związku z tym że nie oczekiwaliśmy żadnego wyniku funkcji, został on domyślnie zdefiniowany. Unit jest w w Scali typem nie określnym (znanym z Javy jako void).

Poniżej znajduje się definicja funkcji której zwracana wartość jest istotna:

scala> def five() = { 5 }
five: ()Int

Należy zauważyć w tym przykładzie iż Scala podobnie jak Ruby nie wykorzystuje słowa kluczowego return do zwrócenia wartości. Następujący przykład pozwoli nam zrozumieć ten fakt, zwracając przy okazji uwagę na to że w Scali if podobnie jak konstrukcja w Javie ?: zwraca wartość jak normalna funkcja.

scala> def maximum(x:Int, y:Int) = { if (x>y) x else y }
maximum: (Int,Int)Int

W w/w przykładzie widzimy również że podobnie jak to miało miejsce w definicji zmiennych tak również w tym miejscu Scala potrafi “domyśleć” się typu zwracanego. Ta właściwość będzie jeszcze nie jednokrotnie widoczna w trakcie nauki Scali i to w sposób o wiele bardziej zaawansowany.

Na koniec chciałbym zostawić czytelnika z przykładem do przemyślenia :

scala> List(1, 2, 3, 4, 5).foreach( (x) => println(x) )
scala> List(1, 2, 3, 4, 5).foreach( x => println(x) )
scala> List(1, 2, 3, 4, 5).foreach( println _ )

Wszystkie 3 przykłady są tożsame, i oczywiście wynik ich działanie jest identyczny. Jako dodatkowy przykład wykorzystania '_' przedstawiam:

import Predef._

który powinien rzucić trochę światła na nasz poprzedni przykład. W następnym odcinku zacznę od szczegółowego wyjaśnienia magicznego '_'. Zainteresowanych i niecierpliwych już teraz zapraszam do korzystania ze strony domowej Scali scala-lang.org gdzie zawsze można zdobyć dodatkowe informacje. Polecam również zaglądanie do źródeł samej biblioteki Scali jako źródła informacji o Scali.

blog comments powered by Disqus