29 kwietnia 2012

Definiowanie symboli przez val w Scali - wartości również jako funkcje

Za 1.3 Wartości niezmienne:

"Za pomocą słowa kluczowego val można w języku Scala definiować wartości niezmienne."

Wartością może być znana programistom Javy liczba, napis lub referencja.
scala> val n = 10
n: Int = 10
Na uwagę zasługuje sposób, w jaki interpreter przedstawia wartość - n: Int = 10. Spróbuję skorzystać z tej wiedzy, aby zdefiniować n ponownie.
scala> val n: Int = 10
n: Int = 10
Być może istnieją inne sposoby deklarowania wartości, ale dla mnie wystarczy składnia
val [symbol] : [typ] = [wartość]
Za [symbol] mogę podstawić własną nazwę - identyfikator lub jak to nazywa się w Clojure - symbol. Następnie mamy [typ] i później przypisanie [wartość].

I teraz najlepsze, wartością [wartość] może być również funkcja. To jest istotna różnica między Javą a Scalą.

Moje (niewielkie) doświadczenie z F# pozwoliło mi przyswoić już sobie składnię deklaracji funkcji z symbolem implikacji =>. Po jednej stronie mamy typ danych wejściowych, a po drugiej wyjściowych. Po znaku przypisania składnia podobna, ale już definiujemy ciało funkcji, a nie jej sygnaturę (pojęcia użyte luźno, więc proszę purystów językowych o wyrozumiałość).
scala> val f:Int => Int = x => x * 3
f: Int => Int = <function1>
Proste, nieprawdaż? Wywołanie funkcji f pozostawiam Wam do samodzielnego rozgryzienia (podpowiedź: jak w Javie).

Warte spróbowania i unaocznienia pojęcia funkcji jako wartości jest wykonanie symbolu funkcyjnego (w powyższym przykładzie f).
scala> f
res15: Int => Int = <function1>
Pojawi się sygnatura funkcji, na którą wskazuje symbol (funkcyjny). Dodatkowo, od tej pory res15 jest również tym, na co wskazywał symbol f.

A na koniec inna ciekawostka: spróbuj wywołać wartość liczbową z parametrem wejściowym, np. powyższy symbol n jakby wskazywał na funkcję.
scala> n
res13: Int = 10

scala> n(2)
<console>:9: error: Int does not take parameters
              n(2)
               ^
Chciałbym napisać, że stała to również funkcja, która akceptuje zero parametrów wejściowych, ale czym różniłoby się to od funkcji bezparametrowej?! A może za bardzo chcę rozróżniać między nimi, a nie ma po co?! Jak czytam w Symbol funkcyjny:

"Wprowadzając język pierwszego rzędu najpierw określamy jego alfabet τ czyli zbiór symboli funkcyjnych, symboli relacyjnych i stałych. Każdy z tych symboli ma jednoznacznie określony charakter (tzn. wiadomo czy jest to stała, czy symbol funkcyjny, czy też predykat) i każdy z symboli funkcyjnych i predykatów ma określoną arność (która jest dodatnią liczbą całkowitą)."

co sugeruje, że nawet jeśli teoretycznie stała jest odpowiednikiem funkcji zeroargumentowej (lub odwrotnie), to faktycznie z góry wiemy, że mamy do czynienia z symbolem wskazującym na stałą lub funkcją (dowolnej arności). Trzeba mi było uważać na studiach - może wtedy takie rzeczy nie byłyby dla mnie swego rodzaju mentalnym wyzwaniem. A jakie jest Twoje zdanie w temacie? Co byłoby interesujące dla Ciebie w poznawaniu Scali?