13 kwietnia 2013

Podkreślnik jako substytut parametrów funkcji w Scali

Zacząłem bawić się podkreślnikiem "_" w Scali jako substytut parametrów funkcji.

Jakoś tak się potoczyło, że trafiłem na stronę Wikipedii o literałach funkcyjnych w Scali, na której znalazłem poniższy przykład (zmodyfikowałem go nieznacznie na potrzeby tego wpisu):
List(1, 2, 3, 4).reduceLeft(_ + _)
A pod nim komentarz:

"// Each underscore stands for a new unnamed parameter in the anonymous function.
// This results in an even shorter equivalent to the anonymous function above."


Zwykle tak właśnie u mnie bywa, że drobne rzeczy mają niebagatelny wpływ na moje rozumowanie sprawy i ten, z pozoru błahy, komentarz przypomniał mi o moich dokonaniach w serwisie Coursera w kursie o Scali.

Nie mogę narzekać na ostatnie wyniki z zadań w Functional Programming Principles in Scala.

Idzie całkiem gładko i niezwykle przyjemnie. Nie raz już pisałem o tym szkoleniu i polecam je każdemu - choćby dla poszerzenia horyzontów.

W sekcji Extra Hints do zadań w Week 2: Higher Order Function można było znaleźć taką podpowiedź:

"Most of the solutions for this assignment can be written as one-liners. If you have more, you probably need to rethink your solution. In other words, this assignment needs more thinking (whiteboard, pen and paper) than coding ;-)."

Największym wyzwaniem intelektualnym było wyrażenie exists przez forall, ale coś mi mówiło, że mogę więcej przy definicji funkcji podobnych do poniższej:
def funkcjaZwracajacaFunkcje(arg: Int): Int => Int = e => e + arg
Wywołanie funkcji funkcjaZwracajacaFunkcje zwraca funkcję jednego parametru, który dodawany jest do poprzedniego.
scala> funkcjaZwracajacaFunkcje(5)(4)
res9: Int = 9
Nic odkrywczego, poza podstawową znajomością składni Scali.

I kiedy przeczytałem o podkreślniku jako symbolu zastępczym dla kolejnych parametrów funkcji w 8.5 Placeholder syntax (z książki Programming in Scala, First Edition) wiedziałem już, czego brakowało mi w moich jednolinijkowcach na courserze!

Zamieniłem definicję funkcji na korzystającą z podkreślnika!
def funkcjaZwracajacaFunkcje(arg: Int): Int => Int = _ + arg
To jest znacznie przyjemniejsze dla (mojego) oka. Tu dostrzegam wartość stosowania Scali nad odpowiednikiem w Javie (który nota bene wymagałby zastosowania dodatkowych bibliotek i/lub klas anonimowych!)