Perché Scala richiede che le funzioni abbiano un tipo di reso esplicito?

11

Recentemente ho iniziato a imparare a programmare in Scala, ed è stato divertente finora. Mi piace molto la capacità di dichiarare le funzioni all'interno di un'altra funzione che sembra solo una cosa intuitiva da fare.

Una cosa che mi piace di Scala è il fatto che Scala richiede un tipo di ritorno esplicito nelle sue funzioni . E sento che questo ostacola l'espressività della lingua. Inoltre è solo difficile da programmare con quel requisito. Forse è perché vengo da Javascript e Ruby comfort zone. Ma per un linguaggio come Scala che avrà tonnellate di funzioni connesse in un'applicazione, non riesco a immaginare come faccio a pensare in testa esattamente quale tipo la funzione specifica che sto scrivendo dovrebbe tornare con le ricorsioni dopo le ricorsioni.

Questo requisito della dichiarazione del tipo di reso esplicita sulle funzioni, non mi infastidisce per linguaggi come Java e C ++. Le ricorsioni in Java e C ++, quando avvenivano, spesso venivano gestite da 2 a 3 funzioni max. Mai diverse funzioni concatenate insieme come Scala.

Quindi immagino che mi stia chiedendo se c'è una buona ragione per cui Scala dovrebbe avere il requisito di funzioni con un tipo di ritorno esplicito?

    
posta garbage collection 03.10.2012 - 05:15
fonte

1 risposta

15

Scala non richiede un tipo di ritorno esplicito sulle funzioni tutte , solo ricorsive. Il motivo è che l'algoritmo di inferenza del tipo di Scala è (qualcosa di simile a) una semplice scansione dall'inizio alla fine che non è in grado di guardare avanti.

Questo significa che una funzione come questa:

def fortuneCookieJoke(message: String) = message + " in bed."

non ha bisogno di un tipo restituito, dal momento che il compilatore Scala può vedere chiaramente, senza usare variabili logiche o guardando qualcosa di diverso dai parametri del metodo, che il tipo restituito deve essere String .

D'altra parte, una funzione come questa:

def mapInts(f: (Int) => Int, l: List[Int]) = l match {
  case Nil => Nil
  case x :: xs => f(x) :: mapInts(f, xs)
}

causerà un errore in fase di compilazione, perché il compilatore di Scala non può vedere, senza usare né lookahead né variabili logiche, esattamente quale sia il tipo di mapInts . Il massimo che si possa dire, se fosse abbastanza intelligente, è che il tipo restituito è un supertipo di List[Nothing] , poiché Nil è di quel tipo. Questo non gli consente di avere informazioni sufficienti per determinare con precisione il tipo di ritorno di mapInts .

Si noti che questo è specifico per Scala, e che ci sono altre lingue tipizzate staticamente (la maggior parte della famiglia Miranda / Haskell / Clean, la maggior parte della famiglia ML e alcune altre sparpagliate) che usano molto più completo e capace digita algoritmi di inferenza di Scala. Inoltre, sii consapevole che questa non è interamente colpa di Scala; sottotipizzazione nominale e tipo di inferenza di tipo intero sono fondamentalmente in disaccordo tra loro, ei progettisti di Scala hanno scelto di privilegiare il primo rispetto a quest'ultimo per la compatibilità con Java, mentre i linguaggi funzionali "più puri" staticamente sono stati progettati principalmente con il scelta opposta in mente.

    
risposta data 03.10.2012 - 05:52
fonte

Leggi altre domande sui tag