Scala

Od dłuższego czasu w moim TODO leży zapoznanie się z językiem Scala. I oto nadszedł czas na mój pierwszy rzut oka na ten język.
Scala jest silnie typowanym językiem funkcyjnym, który działa na wirtualnej maszynie Javy i może odwoływać się do klas napisanych w Javie.
Sprawdźmy na przykładach co ciekawego Scala ma do zaoferowania.

Zdefiniujmy następującą klasę:

scala> case class Osoba(imie: String, nazwisko: String)
defined class Osoba

Ten dziwny twór definiuje klasę Osoba z dwuargumentowym konstruktorem, która posiada zaimplementowane metody euqals, toString i hashCode. Dodatkowo posiada też pola o nazwach identycznych z parametrami konstruktora, które inicjowane są wartościami tych parametrów. A wszystko to dzieje się automatycznie dzięki jednemu słowu case :D

Sprawdźmy jak zadziała porównanie dwóch obiektów:

scala> val os1 = Osoba("Jan", "Kowalski")
os1: Osoba = Osoba(Jan,Kowalski)

scala> val os2 = Osoba("Jan", "Kowalski")
os2: Osoba = Osoba(Jan,Kowalski)

scala> os1.eq(os2)
res33: Boolean = false

scala> os1==os2
res34: Boolean = true

Jak widać operator == porównuje wartości obiektu, a nie referencje. Metoda eq porównuje zaś referencje. Odwrotnie niż w Javie, ale IMHO bardziej intuicyjnie.

Zdefinijujmy teraz trzy funkcje:

def biezacyCzas() = {
println("Sprawdzam czas")
System.nanoTime
}
def sprawdzCzas(t: => Long) = {
println("Parametr: "+t)
t
}
def sprawdzCzas2(t: Long) = {
println("Parametr: "+t)
t
}

i przyjrzymy się wynikom ich wykonania:

scala> sprawdzCzas(biezacyCzas())
Sprawdzam czas
Parametr: 2745273638129
Sprawdzam czas
res3: Long = 2745273796809

scala> sprawdzCzas2(biezacyCzas)
Sprawdzam czas
Parametr: 2745354364591
res4: Long = 2745354364591

Jak widzimy pierwsza funkcja sprawdź czas działa na referencji do funkcji biezacyCzas i za każdym razem, gdy następuje odwołanie do parametru t, funkcja ta jest wywoływana. W drugim przypadku do funkcji sprawdzCzas2 przekazywany jest wynik działania funkcji biezacyCzas. Zauważmy, że funkcja zwraca wartość ostatniego wyrażenia – nie ma słowa kluczowego return – chyba, że zwracanym typem jest Unit (odpowiednik javowego void), wówczas funkcja nie zwraca wartości.

Zdefiniujmy teraz następującą klasę:

class ApUp {
def apply(in: Int) = println(in.toString)
def update(k: Int, v: String) = println(k+" = "+v)
}

scala> val a = new ApUp
a: ApUp = ApUp@11f91ac

scala> a(44)
44

scala> a(33) = "Hello"
33 = Hello

Jak widzimy metody apply i update dają nam bardzo wygodne mechanizmy. Funkcje, które w języku Scala są również obiektami, wykorzystują metodę apply. Wywołanie funkcji funkcja(parametr), może być również implementowane przy użyciu metody apply: funkcja.apply(parametr). Z mechanizmu update korzysta w Scali klasa HashMap.

Na dziś wystarczy, ciąg dalszy nastąpi :)

Dodaj komentarz