Dobrym zwyczajem (przy funkcjach publicznych), a często wymaganiem (przy funkcjach rekurencyjnych) jest jawne zadeklarowanie typu zwracanej wartości funkcji. Typ zwracanej wartości podajemy zaraz za nawiasami okrągłymi z parametrami, po dwukropku, a zaraz przed nawiasem.

def sum(x: Int, y: Int): Int = x + y

Deklaracja typu wartości zwracanej z funkcji jest opcjonalna i często “wyliczona” przez kompilator.

def sum(x: Int, y: Int) = x + y

Powyższa definicja sum jest równie poprawna jak poprzednia.

Kompilator musi być zawsze w stanie wyznaczyć typ, ale wcale nie musi to być typ oczekiwany. Jeśli jednak jest podany jawnie musi być zgodny z typem wyrażenia, które stanowi ciało funkcji.

Definicja sum mogłaby być jednak taka:

def sum(x: Int, y: Int): Number = x + y

Mogłaby być również Unit, czyli określona, ale pusta.

def sum(x: Int, y: Int): Unit = x + y

Wywołaj wszystkie ze wspomnianych definicji funkcji w Scala REPL. Ostatnia może być szczególnie zaskakująca.

scala> def sum(x: Int, y: Int): Unit = x + y
sum: (x: Int, y: Int)Unit

scala> sum(1,2)

A co z definicją funkcji def sum(a: String, b: String): T? Jakie moglibyśmy wyobrazić sobie typy zwracane przez nią? Jakie może być T i jaką mogłoby mieć to interpretację?

Czy T mogłoby być String?

def sum(a: String, b: String): String = ???

A jaka mogłaby być implementacja funkcji zwracającej Int?

def sum(a: String, b: String): Int = ???

W pierwszym przypadku będzie to łączenie ciągów (konkatenacja), a w drugim suma ich długości. Spróbuj je zaimplementować samodzielnie.

Fork me on GitHub