Niedawno zacząłem uczyć się programowania w Scali i jak dotąd było fajnie. Naprawdę podoba mi się możliwość deklarowania funkcji w ramach innej funkcji, co wydaje się intuicyjne.
Jedno wkurzenie, jakie mam o Scali, to fakt, że Scala wymaga wyraźnego typu zwrotu w swoich funkcjach . I czuję, że przeszkadza to w ekspresji języka. Trudno też zaprogramować ten wymóg. Może dlatego, że pochodzę ze Javascript i Ruby comfort zone. Ale dla języka takiego jak Scala, który będzie miał mnóstwo połączonych funkcji w aplikacji, nie mogę sobie wyobrazić, jak burzę mózgów w mojej głowie dokładnie, jaki typ konkretnej funkcji, którą piszę, powinien powrócić z rekurencjami po rekurencjach.
Ten wymóg wyraźnej deklaracji typu zwrotu dla funkcji nie przeszkadza mi w przypadku języków takich jak Java i C ++. Rekurencje w Javie i C ++, kiedy się zdarzały, często zajmowały maksymalnie 2 do 3 funkcji. Nigdy nie połączono ze sobą kilku funkcji, takich jak Scala.
Myślę, że zastanawiam się, czy istnieje dobry powód, dla którego Scala powinna mieć wymóg, aby funkcje miały jawny typ zwrotu?
źródło
Odpowiedzi:
Scala nie wymaga jawnego typu zwrotu dla wszystkich funkcji, tylko te rekurencyjne. Powodem tego jest to, że algorytm wnioskowania typu Scali jest (coś bliskiego) prostym skanem od początku do końca, który nie jest w stanie spojrzeć w przyszłość.
Oznacza to, że taka funkcja:
nie potrzebuje typu zwracanego, ponieważ kompilator Scala może wyraźnie zobaczyć, bez użycia zmiennych logicznych lub patrzenia na nic innego niż parametry metody, że musi to być typ zwracany
String
.Z drugiej strony taka funkcja:
spowoduje błąd czasu kompilacji, ponieważ kompilator Scala nie widzi, bez użycia zmiennych typu lookahead lub zmiennych logicznych, dokładnie tego, jaki jest typ
mapInts
. Gdyby był wystarczająco sprytny, mógłby powiedzieć, że typ zwracany jest nadtypemList[Nothing]
, ponieważNil
jest tego typu. Nie daje to nigdzie blisko informacji wystarczających do dokładnego określenia rodzaju zwrotumapInts
.Należy pamiętać, że jest to specyficzne dla Scali i że istnieją inne języki o typie statycznym (większość rodziny Miranda / Haskell / Clean, większość rodziny ML i kilka innych rozproszonych), które używają znacznie bardziej kompleksowych i zdolnych algorytmów wnioskowania typu niż używa Scala. Pamiętaj też, że nie jest to całkowicie wina Scali; nominalne podtypy i wnioskowanie o typach modułów są zasadniczo sprzeczne ze sobą, a projektanci Scali zdecydowali się faworyzować te pierwsze ze względu na kompatybilność z Javą, podczas gdy „czystsze” statyczne języki funkcjonalne zostały zaprojektowane głównie z przeciwny wybór.
źródło
case Nil
nie byłby rzeczywiście pustyList[Int]()
? W takim przypadku wystarczająco inteligentny kompilator mógłby to rozgryźć. To chyba wszystko w roli Diabelskiego Adwokata.