21 kwietnia 2012

scala> (-48 to Euro2012)


Lektura Functional Scala: Introduction pozwoliła mi ułożyć sobie w głowie koncepcję programowania funkcyjnego. Mimo ukierunkowania autora na Scalę, prawie żadna z części nie wskazywała na jakikolwiek związek z tym językiem. Wystarczy 30 minut skupienia i zrozumienie cech paradygmatu funkcyjnego powinno być jaśniejsze. Mi pomogło znacznie.

Najbardziej płodną sekcją artykułu była końcówka Stateless vs. Stateful, w której dotarło do mnie, że:

Skutek uboczny jest sposobem na przechowanie tymczasowego wyniku obliczeń na potrzeby innych części aplikacji. W programowaniu funkcyjnym zmienne nie istnieją, więc jedynym sposobem na przekazanie wyniku obliczeń jest użycie rekurencji (przekazywanie wyniku funkcji samej sobie) lub zwrócenie go (przekazanie wyniku innym funkcjom).

Podczas lektury miałem uruchomioną konsolę scala i bawiłem się poznanymi konstrukcjami. Nie zagłębiam się w lekturę składni Scali, więc idzie mi jak po grudzie i próbuję odgadywać, jak mogłoby dane wywołanie wyglądać. Najbardziej zaskakujące jest, że bezwiednie wpisuję wywołania w składni Clojure - zaczynam nawiasem! Stało się to dla mnie naturalne! Całkowicie przestawiłem swoje myślenie na "wszechobecne funkcje" w Clojure na "metody są przypisane do obiektów" w Scali. Scala wymusza u mnie przestawienie się na myślenie obiektowe z dodatkiem funkcyjnym.

Poniżej wycinek moich wyczynów scalowych. Samo środowisko często samo z siebie podpowiada co mogłoby być właściwe w danym kontekście. Bajka!
$ scala
Welcome to Scala version 2.10.0-M2 (OpenJDK 64-Bit Server VM, Java 1.8.0-jdk8-b29).
Type in expressions to have them evaluated.
Type :help for more information.

scala> (1 to 9)
res0: scala.collection.immutable.Range.Inclusive = Range(1, 2, 3, 4, 5, 6, 7, 8, 9)

scala> Range(1, 4)
res1: scala.collection.immutable.Range = Range(1, 2, 3)
Zwróć uwagę na sufix Inclusive przy nazwie klasy, która obsługuje pierwszy przykład vs drugi.
scala> (0 to 10).foldLeft(0)
<console>:8: error: missing arguments for method foldLeft in trait TraversableOnce;
follow this method with `_' if you want to treat it as a partially applied function
              (0 to 10).foldLeft(0)
                                ^

scala> (0 to 10).foldLeft(0)_
res3: ((Int, Int) => Int) => Int = <function1>

scala> val fl = (0 to 10).foldLeft(0)_
fl: ((Int, Int) => Int) => Int = <function1>

scala> fl(_+_)
res4: Int = 55

scala> val fl = (0 to 10).reduceLeft_
<console>:7: error: value reduceLeft_ is not a member of scala.collection.immutable.Range.Inclusive
       val fl = (0 to 10).reduceLeft_
                          ^

scala> val fl = (0 to 10).reduceLeft _
fl: ((Int, Int) => Int) => Int = <function1>

scala> fl(_+_)
res5: Int = 55