La biblioteca delle collezioni di Scala 2.8 è un caso della "nota suicida più lunga della storia"? [chiuso]


873

Ho appena iniziato a esaminare la reimplementazione della libreria delle collezioni Scala, che arriverà nell'imminente versione 2.8 . Chi ha familiarità con la libreria dalla 2.7 noterà che la libreria, dal punto di vista dell'uso, è cambiata poco. Per esempio...

> List("Paris", "London").map(_.length)
res0: List[Int] List(5, 6)

... funzionerebbe in entrambe le versioni. La biblioteca è estremamente utilizzabile : in effetti è fantastica. Tuttavia, quelli che in precedenza non avevano familiarità con Scala e che cercavano in giro per avere un'idea della lingua ora devono dare un senso alle firme dei metodi come:

def map[B, That](f: A => B)(implicit bf: CanBuildFrom[Repr, B, That]): That

Per una funzionalità così semplice, questa è una firma scoraggiante e che mi trovo a fatica a capire. Non che penso che Scala sia mai stato probabilmente il prossimo Java (o / C / C ++ / C #) - Non credo che i suoi creatori lo stessero puntando su quel mercato - ma penso che sia / era certamente fattibile che Scala diventasse il prossimo Ruby o Python (ovvero per ottenere una significativa base di utenti commerciali)

  • Questo scoraggerà le persone a venire alla Scala?
  • Questo darà alla Scala un brutto nome nel mondo commerciale come un giocattolo accademico che solo gli studenti di dottorato dedicati possono capire? I CTO e i responsabili del software si spaventeranno?
  • La riprogettazione della biblioteca è stata un'idea sensata?
  • Se stai usando Scala commercialmente, sei preoccupato per questo? Stai pianificando di adottare immediatamente 2.8 o aspetti di vedere cosa succede?

Steve Yegge una volta attaccò Scala (a mio avviso erroneamente) per quello che vedeva come il suo sistema di tipi complicato. Temo che qualcuno avrà una giornata campale diffondendo FUD con questa API (in modo simile a come Josh Bloch ha spaventato il JCP dall'aggiungere chiusure a Java).

Nota - Dovrei essere chiaro che, sebbene ritenga che Joshua Bloch sia stato influente nel rifiuto della proposta di chiusure BGGA, non lo attribuisco a nient'altro che alle sue convinzioni oneste che la proposta rappresentasse un errore.


Nonostante ciò che mia moglie e i miei colleghi continuano a dirmi, non credo di essere un idiota: ho una buona laurea in matematica presso l' Università di Oxford , e sto programmando commercialmente da quasi 12 anni e in Scala da circa un anno (anche commercialmente).

Si noti che il titolo del soggetto infiammatorio è una citazione fatta sul manifesto di un partito politico britannico nei primi anni '80 . Questa domanda è soggettiva ma è una domanda autentica, l'ho fatta in CW e vorrei alcune opinioni in merito.


10
Fud è sinonimo di paura, incertezza e dubbio: penso che esprima abbastanza chiaramente il tono del discorso di Josh Bloch, che sono anche d'accordo, è ben argomentato e ragionato, ecc. Se vedi le modifiche, inizialmente non ho messo fud perché Non volevo implicare -ve connotazioni
oxbow_lakes,

32
Questa domanda è stata menzionata nel discorso di apertura di Martin Odersky ai giorni della Scala 2010 days2010.scala-lang.org/node/136
Binil Thomas

7
Ciò che amo di Scala è che non devi capire che è un sistema di tipo complesso per fare cose semplici ed eleganti. la sua sintassi può essere scoraggiante, ma ti assicura una cosa, non c'è "magia", ad esempio la magia è parte del linguaggio, è un approccio molto coraggioso e intelligente, penso che tu abbia un linguaggio in grado di creare nuovi DSL e nuovi mini lingue al suo interno, sì, con le mani sbagliate Scala può essere un'ottima aggiunta alla tua cena italiana, ma una volta che ti ci abitui, è una lingua straordinaria
Eran Medan,

87
In che modo questa domanda può essere "non costruttiva" quando ha portato a @MartinOdersky a rivalutare l'usabilità di Scala e a far nascondere al sistema di documentazione i dettagli del tipo di sistema, per non parlare di una discussione illuminante?
Jerry101,

14
In effetti, SO è solo per tecnicità con il formato giusto. Se hai qualcosa di delicato, intrigante e di vasta portata, ti preghiamo di guardare altrove. Lunga vita alla mentalità burocratica.
Qed

Risposte:


892

Spero non sia una "nota suicida", ma posso capire il tuo punto. Colpisci su ciò che è allo stesso tempo un punto di forza e un problema di Scala: la sua estensibilità . Questo ci consente di implementare la maggior parte delle funzionalità principali nelle librerie. In alcuni altri linguaggi, sequenze con qualcosa di simile mapo collectsarebbero incorporate e nessuno deve vedere tutti i cerchi che il compilatore deve attraversare per farli funzionare senza problemi. Alla Scala, è tutto in una biblioteca, e quindi all'aperto.

In effetti la funzionalità mapsupportata dal suo tipo complicato è piuttosto avanzata. Considera questo:

scala> import collection.immutable.BitSet
import collection.immutable.BitSet

scala> val bits = BitSet(1, 2, 3)
bits: scala.collection.immutable.BitSet = BitSet(1, 2, 3)

scala> val shifted = bits map { _ + 1 }
shifted: scala.collection.immutable.BitSet = BitSet(2, 3, 4)

scala> val displayed = bits map { _.toString + "!" }
displayed: scala.collection.immutable.Set[java.lang.String] = Set(1!, 2!, 3!)

Vedi come ottieni sempre il miglior tipo possibile? Se si mappano da Ints a Intsi ottiene di nuovo a BitSet, ma se si mappano da Ints a Strings, si ottiene un generale Set. Sia il tipo statico che la rappresentazione runtime del risultato della mappa dipendono dal tipo di risultato della funzione che gli è stata passata. E questo funziona anche se il set è vuoto, quindi la funzione non viene mai applicata! Per quanto ne so, non esiste un altro framework di raccolta con funzionalità equivalenti. Tuttavia, dal punto di vista dell'utente, è così che dovrebbero funzionare le cose .

Il problema che abbiamo è che tutta la tecnologia intelligente che rende possibile ciò si diffonde nelle firme dei tipi che diventano grandi e spaventose. Ma forse un utente non dovrebbe mostrare per impostazione predefinita la firma del tipo completo di map? Che ne dici se alzasse lo sguardo mapin BitSetlei ottiene:

map(f: Int => Int): BitSet     (click here for more general type)

I documenti non mentirebbero in quel caso, perché dal punto di vista dell'utente la mappa ha davvero il tipo (Int => Int) => BitSet. Ma mapha anche un tipo più generale che può essere ispezionato facendo clic su un altro collegamento.

Non abbiamo ancora implementato funzionalità come questa nei nostri strumenti. Ma credo che dobbiamo farlo, per evitare di spaventare le persone e per fornire informazioni più utili. Con strumenti del genere, si spera che framework e librerie intelligenti non diventino note suicide.


107
Mi sento uno scolaretto cattivo! Grazie mille per il tempo dedicato a rispondere qui. Penso che l'equilibrio delle risposte mi abbia dimostrato che non devo preoccuparmi; ci saranno abbastanza persone che non sono affatto intimidite.
oxbow_lakes,

164
No, penso che tu abbia assolutamente ragione a colpirlo su questo punto. E le altre persone avranno paura a meno che non facciamo qualcosa al riguardo.
Martin Odersky,

33
Martin, mi piace il tuo suggerimento di mostrare firme di un metodo semplificato e nascondere i dettagli generali dietro un collegamento.
Derek Mahar,

18
Penso che una soluzione che possa funzionare almeno sia ulteriori spiegazioni nei documenti. Non troverei le firme così intimidatorie, se non fosse per il fatto che la maggior parte dei metodi (e persino la maggior parte delle classi) non hanno più di una sola frase che descriva il loro scopo e il loro funzionamento.
Nick Johnson,

98
Aggiornamento: l'ultima versione di Scala 2.8 ha un meccanismo come quello che ho descritto. Se cerchi BitSet nei scaladocs trovi: def map [B] (f: (Int) ⇒ B): BitSet [B] [use case] Crea una nuova raccolta applicando una funzione a tutti gli elementi di questo bitset.
Martin Odersky,

226

Non ho un dottorato di ricerca, né alcun altro tipo di laurea né in CS né in matematica né in effetti nessun altro campo. Non ho alcuna esperienza precedente con Scala né con nessun altro linguaggio simile. Non ho esperienza con sistemi di tipo anche remotamente comparabili. In effetti, l'unico linguaggio che ho più di una semplice conoscenza di cui ha persino un sistema di tipi è Pascal, non esattamente noto per il suo sofisticato sistema di tipi. (Anche se fa avere tipi di raggio, che per quanto ne so praticamente nessun altro linguaggio ha, ma che non è davvero rilevante qui.) Le altre tre lingue che conosco sono essenziali, Smalltalk e Ruby, nessuno dei quali nemmeno un sistema di tipo.

Eppure, non ho alcun problema a capire la firma della mapfunzione che hai pubblicato. Mi sembra quasi la stessa firma che mapha in ogni altra lingua che abbia mai visto. La differenza è che questa versione è più generica. Sembra più una cosa C ++ STL che, diciamo, Haskell. In particolare, si estrae dal tipo di raccolta concreto richiedendo solo che l'argomento sia IterableLike, e si estrae anche dal tipo di ritorno concreto richiedendo solo l'esistenza di una funzione di conversione implicita che può costruire qualcosa da quella raccolta di valori di risultato. Sì, è piuttosto complesso, ma in realtà è solo un'espressione del paradigma generale della programmazione generica: non dare per scontato nulla che non sia effettivamente necessario.

In questo caso, in maprealtà non è necessario che la raccolta sia un elenco o sia ordinata o ordinabile o qualcosa del genere. L'unica cosa che mapimporta è che possa accedere a tutti gli elementi della collezione, uno dopo l'altro, ma senza un ordine particolare. E non ha bisogno di sapere quale sia la raccolta risultante, deve solo sapere come costruirla. Quindi, questo è ciò che richiede la firma del suo tipo.

Quindi, invece di

map :: (a → b)[a][b]

che è la firma di tipo tradizionale per map, è generalizzato per non richiedere una struttura di dati concreta Listma piuttosto soloIterableLike

map :: (IterableLike i, IterableLike j)(a → b) → i → j

che viene poi ulteriormente generalizzato richiedendo solo l'esistenza di una funzione in grado di convertire il risultato in qualsiasi struttura di dati l'utente desideri:

map :: IterableLike i ⇒ (a → b) → i → ([b] → c) → c

Ammetto che la sintassi è un po 'più complessa, ma la semantica è la stessa. Fondamentalmente, inizia da

def map[B](f: (A) ⇒ B): List[B]

che è la firma tradizionale per map. (Nota come, a causa della natura orientata agli oggetti di Scala, il parametro della lista di input svanisce, perché ora è il parametro del ricevitore implicito che ogni metodo in un sistema OO a spedizione singola ha.) Quindi si è generalizzato da un concreto Listad un più generaleIterableLike

def map[B](f: (A) ⇒ B): IterableLike[B]

Ora, sostituisce la IterableLikeraccolta dei risultati con una funzione che produce , beh, praticamente qualsiasi cosa.

def map[B, That](f: A ⇒ B)(implicit bf: CanBuildFrom[Repr, B, That]): That

Che credo davvero non sia così difficile da capire. C'è davvero solo un paio di strumenti intellettuali di cui hai bisogno:

  1. Devi sapere (approssimativamente) cos'è map. Se hai dato solo la firma del tipo senza il nome del metodo, lo ammetto, sarebbe molto più difficile capire cosa sta succedendo. Ma dal momento che già sapete che cosa mapsi dovrebbe fare, e si sa che cosa la sua firma tipo dovrebbe essere, è possibile analizzare rapidamente la firma e attenzione per le anomalie, come "perché questo mapintroito due funzioni come argomenti, non uno?"
  2. Devi essere in grado di leggere effettivamente la firma del tipo. Ma anche se non hai mai visto Scala prima, questo dovrebbe essere abbastanza facile, dal momento che è davvero solo una miscela di sintassi di tipo che già conosci da altre lingue: VB.NET usa parentesi quadre per il polimorfismo parametrico e usa una freccia per indicare il tipo di ritorno e due punti per separare il nome e il tipo, è in realtà la norma.
  3. Devi sapere più o meno di cosa tratta la programmazione generica. (Che non è quello difficile da capire, dal momento che è praticamente tutto spiegato nel nome: è letteralmente solo programmando in modo generico).

Nessuno di questi tre dovrebbe dare a nessun programmatore professionista o anche un hobbista un forte mal di testa. mapè stata una funzione standard in quasi tutte le lingue progettate negli ultimi 50 anni, il fatto che lingue diverse abbiano una sintassi diversa dovrebbe essere ovvio per chiunque abbia progettato un sito Web con HTML e CSS e non è possibile abbonarsi a una programmazione anche remota mailinglist correlata senza alcuni fastidiosi fanboy C ++ della chiesa di Santo Stefano che spiegano le virtù della programmazione generica.

Sì, Scala è complessa. Sì, Scala ha uno dei sistemi di tipo più sofisticati conosciuti dall'uomo, in grado di competere e persino di superare linguaggi come Haskell, Miranda, Clean o Cyclone. Ma se la complessità fosse un argomento contro il successo di un linguaggio di programmazione, il C ++ sarebbe morto molto tempo fa e tutti scriveremmo Scheme. Ci sono molte ragioni per cui Scala probabilmente non avrà successo, ma il fatto che i programmatori non possano preoccuparsi di accendere il cervello prima di sedersi davanti alla tastiera non sarà probabilmente il principale.


36
@Jorg - questa è una risposta fantastica; grazie. Che tu abbia una laurea o no, sei un uomo più brillante di me. L'unico cavillo che ho è che capisco il quadro generale di ciò che sta accadendo nella firma del metodo. Tuttavia, i dettagli sono ancora confusi: il modo in cui viene Thatinferito e collegato al tipo Bè una domanda che mi viene in mente. Dove sono gli impliciti derivanti dall'essere un altro. Anche senza queste osservazioni dettagliate, ritengo personalmente che questa sia una firma complessa. Ma evidentemente ci sono persone come te là fuori che non ne sono affatto spaventate!
oxbow_lakes,

50
Bella spiegazione, ma mi hai convinto ancora di più che la firma del metodo "map" di Scala 2.8 è molto complicata.
Derek Mahar,

11
Un linguaggio che assomiglia a questo: def map [B] (f: (A) ⇒ B): IterableLike [B] è molto più invitante di uno che assomiglia a questo: def map [B, That] (f: A ⇒ B ) (implicito bf: CanBuildFrom [Repr, B, That]): That
Mark Essel,

215
Trovo abbastanza interessante che tu inizi affermando di conoscere solo base, rubino e conversazione, e continuando a non avere un background accademico in materia. ... e poi rivendicare la conoscenza della complessità dei sistemi di tipi in linguaggi come Miranda e Clean; lingue per lo più conosciute solo da seri geek e accademici di linguaggi di programmazione.
Sami,

14
Hai un punto valido che il confronto con Haskell non è corretto in quel "map :: (a -> b) -> [a] -> [b]" è specifico degli Elenchi. Tuttavia, la versione generalizzata, quella della classe Functor, è ancora molto più semplice della versione Scala: class Functor f dove fmap :: (a -> b) -> fa -> fb
Orclev

175

Stessa cosa in C ++ :

template <template <class, class> class C,
          class T,
          class A,
          class T_return,
          class T_arg
              >
C<T_return, typename A::rebind<T_return>::other>
map(C<T, A> &c,T_return(*func)(T_arg) )
{
    C<T_return, typename A::rebind<T_return>::other> res;
    for ( C<T,A>::iterator it=c.begin() ; it != c.end(); it++ ){
        res.push_back(func(*it));
    }
    return res;
}

105
... e dicono che Scala è oscuro. Duh!
missingfaktor

24
Immagina solo come sarebbe stato se fossero stati usati identificatori auto-descrittivi al posto di lettere maiuscole arbitrarie. :-)
Ti Strga,

14
È utile vedere questo confronto, ma sarebbe più giusto se l'implementazione fosse omessa.
Aaron Novstrup,

2
Non sono un grande fan del puntatore a funzione obbligatoria. Chiaramente il tipo di funcdovrebbe essere un parametro template, e dovresti usare result_ofe is_callableper ottenere gli altri tipi e vincolare il sovraccarico impostato appropriatamente :-)
Kerrek SB,

1
mi fanno male gli occhi !!!
Ashkan Kh. Nazary,

71

Bene, posso capire il tuo dolore, ma, francamente, persone come te e io - o praticamente qualsiasi normale utente di Stack Overflow - non siamo la regola.

Quello che voglio dire è che ... la maggior parte dei programmatori non si preoccuperà di quel tipo di firma, perché non li vedranno mai ! Non leggono la documentazione.

Finché hanno visto alcuni esempi di come funziona il codice e il codice non fallisce nel produrre il risultato che si aspettano , non guarderanno mai la documentazione. Quando fallisce, guarderanno la documentazione e si aspettano di vedere esempi di utilizzo in alto.

Con queste cose in mente, penso che:

  1. Chiunque (come nella maggior parte delle persone) che abbia mai incontrato quel tipo di firma deriderà la Scala senza fine se sono predisposti contro di essa, e la considererà un simbolo del potere della Scala se gli piace Scala.

  2. Se la documentazione non è stata migliorata per fornire esempi di utilizzo e spiegare chiaramente a cosa serve un metodo e come utilizzarlo, può ridurre un po 'l'adozione di Scala.

  3. A lungo termine, non importa. Il fatto che Scala possa fare cose del genere renderà le librerie scritte per Scala molto più potenti e sicure da usare. Queste librerie e framework attireranno i programmatori attratti da potenti strumenti.

  4. I programmatori che amano la semplicità e la immediatezza continueranno a utilizzare PHP o linguaggi simili.

Purtroppo, i programmatori Java sono molto interessati agli strumenti di potere, quindi, rispondendo a ciò, ho appena rivisto le mie aspettative sull'adozione della Scala. Non ho alcun dubbio che Scala diventerà un linguaggio tradizionale. Non C-mainstream, ma forse Perl-mainstream o PHP-mainstream.

A proposito di Java, hai mai sostituito il caricatore di classi? Hai mai esaminato ciò che comporta? Java può essere spaventoso, se guardi i luoghi che fanno gli scrittori di framework. È solo che la maggior parte delle persone no. La stessa cosa vale per Scala, IMHO, ma i primi ad adottare hanno la tendenza a guardare sotto ogni roccia che incontrano, per vedere se c'è qualcosa che si nasconde lì.


10
As long as they saw some example of how the code works, and the code doesn't fail them in producing the result they expect, they won't ever look at the documentation. When that fails, they'll look at the documentation and expect to see usage examples at the top.Triste ma vero.
gamliela,

9
@gamliela, non credo che saremo tristi per questo. La conoscenza ha sempre più di un livello da applicare e il lavoro e la fiducia degli altri (peer-review) in qualsiasi sistema possono sempre essere sfruttati, proprio come noi usiamo l'aritmetica quotidianamente e ignoriamo totalmente le algebre spaventose che ci stanno dietro.
LC

55

Questo scoraggerà le persone a venire alla Scala?

Sì, ma impedirà anche alle persone di essere rimandate. Ho considerato la mancanza di raccolte che usano tipi di tipo superiore come una debolezza maggiore da quando Scala ha ottenuto il supporto per tipi di tipo superiore. Rende i documenti API più complicati, ma rende l'utilizzo più naturale.

Questo darà a Scala un brutto nome nel mondo commerciale come un giocattolo accademico che solo gli studenti di dottorato dedicati possono capire? I CTO e i responsabili del software si spaventeranno?

Alcuni probabilmente lo faranno. Non penso che Scala sia accessibile a molti sviluppatori "professionisti", in parte a causa della complessità di Scala e in parte a causa della riluttanza di molti sviluppatori a imparare. I CTO che impiegano tali sviluppatori saranno giustamente spaventati.

La riprogettazione della biblioteca è stata un'idea sensata?

Assolutamente. Rende le raccolte molto più adatte al resto della lingua e al sistema dei tipi, anche se presenta ancora dei bordi irregolari.

Se stai usando scala commerciale, sei preoccupato per questo? Stai pianificando di adottare immediatamente 2.8 o aspetti di vedere cosa succede?

Non lo sto usando commercialmente. Probabilmente aspetterò almeno un paio di giri nella serie 2.8.x prima ancora di provare a introdurlo in modo che i bug possano essere eliminati. Aspetterò anche di vedere quanto EPFL avrà successo nel migliorare il suo sviluppo e i processi di rilascio. Quello che vedo sembra pieno di speranza, ma lavoro per un'azienda conservatrice.

Uno dei temi più generali di "Scala è troppo complicato per gli sviluppatori mainstream?" ...

La maggior parte degli sviluppatori, mainstream o altro, sta mantenendo o estendendo i sistemi esistenti. Ciò significa che la maggior parte di ciò che usano è dettata da decisioni prese molto tempo fa. Ci sono ancora molte persone che scrivono COBOL.

Lo sviluppatore mainstream di domani lavorerà mantenendo ed estendendo le applicazioni che vengono costruite oggi. Molte di queste applicazioni non vengono create dagli sviluppatori mainstream. Gli sviluppatori mainstream di domani useranno il linguaggio utilizzato dagli sviluppatori di successo di oggi di nuove applicazioni.


31
"impedirà anche alle persone di essere rimandate". Questo. assolutamente. scala è il primo linguaggio che rende l'ingegneria con qualcosa di paragonabile a haskell (nella potenza del suo sistema di tipi) una possibilità per molti di noi. non c'è modo di convincere il lavoro a usare l'hashell, ma Scala ha davvero una possibilità e per questo lo adoro e (quando penso abbia senso) cercherò di farlo adottare, o almeno accettato, al lavoro.
Andrew Cooke,

+1 anche da me. Data la premessa che Scala pone più enfasi sulla profondità e il rigore linguistici che sull'approccio di massa, queste risposte si adattano perfettamente.
Carl Smotricz,

16
"Gli sviluppatori mainstream di domani useranno il linguaggio utilizzato dagli sviluppatori di successo di oggi di nuove applicazioni". +1. Detto brillantemente.
Vasil Remeniuk,

46

Un modo in cui la comunità Scala può aiutare ad alleviare la paura dei programmatori che non conoscono la Scala è concentrarsi sulla pratica e insegnare con l'esempio - molti esempi che iniziano in piccolo e diventano gradualmente più grandi. Ecco alcuni siti che adottano questo approccio:

Dopo aver trascorso un po 'di tempo su questi siti, ci si rende presto conto che Scala e le sue biblioteche, sebbene forse difficili da progettare e implementare, non sono così difficili da usare, specialmente nei casi comuni.


43

Ho una laurea presso un'università americana di "mercato di massa" a buon mercato, quindi direi che cado nel mezzo della scala dell'intelligenza dell'utente (o almeno dell'istruzione) :) Mi diletto con Scala da pochi mesi e ho lavorato su due o tre app non banali.

Soprattutto ora che IntelliJ ha rilasciato il suo ottimo IDE con quello che IMHO è attualmente il miglior plugin Scala, lo sviluppo di Scala è relativamente indolore:

  • Trovo di poter usare Scala come "Java senza punto e virgola", cioè scrivo un codice simile a quello che farei in Java, e traggo beneficio un po 'dalla brevità sintattica come quella ottenuta dall'inferenza del tipo. La gestione delle eccezioni, quando lo faccio, è più conveniente. La definizione della classe è molto meno dettagliata senza il bollettino getter / setter.

  • Di tanto in tanto riesco a scrivere una singola riga per realizzare l'equivalente di più righe di Java. Ove applicabile, catene di metodi funzionali come mappa, piega, raccogli, filtra ecc. Sono divertenti da comporre ed eleganti da vedere.

  • Solo raramente mi trovo a beneficiare delle più potenti funzionalità di Scala: chiusure e funzioni parziali (o al curry), abbinamento di modelli ... quel genere di cose.

Come principiante, continuo a lottare con la sintassi concisa e idiomatica. Le chiamate di metodo senza parametri non hanno bisogno di parentesi tranne dove lo fanno; i casi nell'istruzione match hanno bisogno di una freccia grossa ( =>), ma ci sono anche punti in cui è necessaria una freccia sottile ( ->). Molti metodi hanno nomi brevi ma piuttosto criptici come /:o \:- Posso fare le mie cose se sfoglio abbastanza pagine di manuale, ma parte del mio codice finisce per sembrare Perl o rumore di linea. Ironia della sorte, uno dei pezzi più popolari di stenografia sintattica manca in azione: continuo a essere morso dal fatto che Intnon definisce un ++metodo.

Questa è solo la mia opinione: sento che Scala ha il potere del C ++ combinato con la complessità e la leggibilità del C ++. La complessità sintattica del linguaggio rende anche difficile la lettura della documentazione API.

Scala è molto ben ponderata e brillante sotto molti aspetti. Sospetto che molti accademici vorrebbero programmare. Tuttavia, è anche pieno di intelligenza e gotcha, ha una curva di apprendimento molto più alta di Java ed è più difficile da leggere. Se analizzo i forum e vedo quanti sviluppatori stanno ancora lottando con i punti più sottili di Java, non riesco a immaginare che Scala sia mai diventato un linguaggio tradizionale . Nessuna azienda sarà in grado di giustificare l'invio dei suoi sviluppatori a un corso di Scala di 3 settimane quando in precedenza avevano bisogno solo di un corso di Java di 1 settimana.


9
Mi dispiace per tutti i commenti. 1 settimana è uno scherzo per praticamente qualsiasi lingua, ma ciò non impedisce ai manager di mettere in pratica quella battuta. Una volta mi hanno dato 3 giorni per "addestrare" un gruppo di sviluppatori C ++ su Java. Ho chiesto per 5 giorni ma sono stato messo in cortocircuito per motivi di budget.
Carl Smotricz,

22
Per il mio primo lavoro mi è stato dato un libro in C ++ alla fine dell'intervista per imparare prima di iniziare a lavorare il lunedì. Siete tutti wusses.
Tom Hawtin: affronta il

12
@Tom @Erik Voi ragazzi, è facile. Mi sono stati dati gli schemi circuitali al computer (allora nessuna CPU) e mi è stato detto che avevo due ore per correggere un bug durante l'intervista.
Daniel C. Sobral,

33
@Daniel @Tom @Erik Una volta mi è stato dato uno 0 e un 1 e mi è stato chiesto di usarli per risolvere il problema dello zaino in tempo lineare durante l'intervista. Ci ho provato, ma sfortunatamente ho avuto solo il tempo di creare Eclipse (che sospetto sia riducibile allo zaino). #tall_tale
Alex Miller

10
@Alex Questo dimostra mancanza di immaginazione. Posiziona uno zero grande a sinistra e altri due zeri più piccoli a destra: uno sopra l'altro, quello in alto leggermente a sinistra. Posiziona quello tra questi due zeri più piccoli, andando dall'angolo inferiore sinistro all'angolo superiore destro. Supponiamo che sia la possibilità di risolvere lo zaino in tempo lineare. Ecco fatto. :-) +1 per equiparare Eclipse e Zaino, però. :-)
Daniel C. Sobral,

33

Penso che il problema principale con quel metodo sia che (implicit bf : CanBuildFrom[Repr, B, That])non ci sono spiegazioni. Anche se so quali sono gli argomenti impliciti, non c'è nulla che indichi come ciò influisca sulla chiamata. Inseguire lo scaladoc mi lascia solo più confuso (poche delle classi correlateCanBuildFrom hanno persino documentazione).

Penso che un semplice "ci deve essere un oggetto implicito nella possibilità di bfche fornisce un costruttore per gli oggetti di tipo Bnel tipo di ritorno That" avrebbe aiutato un po ', ma è una specie di un concetto inebriante quando tutti si vuole veramente fare è mappa A's per B'S. In realtà, non sono sicuro che sia giusto, perché non so cosa Reprsignifichi il tipo e la documentazione perTraversable certamente non fornisce alcun indizio.

Quindi, sono rimasto con due opzioni, nessuna delle due piacevole:

  • Supponiamo che funzionerà solo come funziona la vecchia mappa e come funziona la mappa nella maggior parte delle altre lingue
  • Scava nel codice sorgente ancora un po '

Capisco che Scala sta essenzialmente esponendo il fegato di come funzionano queste cose e che alla fine questo è un modo per fare ciò che oxbow_lakes sta descrivendo. Ma è una distrazione nella firma.


2
Reprè la rappresentazione attraversabile, cioè. Listo Seto Map. Penso che, come framework, se inizierai a guardare le firme dei metodi (piuttosto che usare i metodi solo copiando esempi), devi prima capire il design generale. IMHO lo Scaladoc dovrebbe essere pieno di esempi di utilizzo
oxbow_lakes il

10
Quindi, come avrei determinato cosa Reprsignificava? Mi sarei aspettato una spiegazione nello scaladoc, ma per me non era ovvio. Penso che questo sia un modello comune nello scaladoc (guarda Actor.reacte Actor.receive- mi è stato detto, e ho visto, che fanno cose totalmente diverse, ma il loro scaladoc è identico).
davetron5000,

7
Sono d'accordo con davetron5000. Conosco bene Scala, ma le definizioni implicite mi fanno ancora male alla testa. E il motivo non è di per sé implicito ma come vengono utilizzati. Ci dovrebbe essere sicuramente una migliore documentazione e supporto degli strumenti per comprendere i tipi di Scala. Detto questo, penso che il sistema di tipi abbia davvero qualcosa di importante da offrire. Ma siamo ancora solo all'inizio del percorso della programmazione ragionevole.
egaga,

22

Sono un principiante alla Scala e onestamente non vedo un problema con quel tipo di firma. Il parametro è la funzione da mappare e il parametro implicito il builder per restituire la raccolta corretta. Chiaro e leggibile.

L'intera cosa è piuttosto elegante, in realtà. I parametri del tipo di generatore consentono al compilatore di scegliere il tipo di ritorno corretto mentre il meccanismo di parametro implicito nasconde questo parametro aggiuntivo all'utente della classe. Ho provato questo:

Map(1 -> "a", 2 -> "b").map((t) => (t._2) -> (t._1)) // returns Map("a" -> 1, "b" -> 2)
Map(1 -> "a", 2 -> "b").map((t) =>  t._2)            // returns List("a", "b")

Questo è polimorfismo fatto bene.

Ora, garantito, non è un paradigma tradizionale e spaventerà molti. Ma attirerà anche molti che apprezzano la sua espressività ed eleganza.


20

Sfortunatamente la firma per la mappa che hai dato è errata per la mappa e ci sono davvero legittime critiche.

La prima critica è che sovvertendo la firma per la mappa, abbiamo qualcosa di più generale. È un errore comune credere che questa sia una virtù per impostazione predefinita. Non lo è. La funzione della mappa è molto ben definita come funzione covariante Fx -> (x -> y) -> Fy con aderenza alle due leggi di composizione e identità. Qualsiasi altra cosa attribuita alla "mappa" è una parodia.

La firma data è qualcos'altro, ma non è una mappa. Ciò che sospetto stia cercando di essere è una versione specializzata e leggermente alterata della firma "traverse" del documento, The Essence of the Iterator Pattern. Ecco la sua firma:

traverse :: (Traversable t, Applicative f) => (a -> f b) -> t a -> f (t b)

Lo convertirò in Scala:

def traverse[A, B](f: A => F[B], a: T[A])(implicit t: Traversable[T], ap: Applicative[F]): F[T[B]

Certo che fallisce - non è abbastanza generale! Inoltre, è leggermente diverso (si noti che è possibile ottenere la mappa eseguendo la corsa attraverso il funzione Identità). Tuttavia, sospetto che se gli autori delle biblioteche fossero più consapevoli delle generalizzazioni delle biblioteche che sono ben documentate (la programmazione applicativa con effetti precede la suddetta), allora non vedremmo questo errore.

In secondo luogo, la funzione della mappa è un caso speciale in Scala a causa del suo uso nella comprensione. Questo purtroppo significa che un progettista di biblioteche meglio attrezzato non può ignorare questo errore senza sacrificare anche lo zucchero sintattico delle comprensioni. In altre parole, se i progettisti della biblioteca Scala dovessero distruggere un metodo, questo potrebbe essere facilmente ignorato, ma per favore non mappare!

Spero che qualcuno ne parli, perché così com'è, sarà più difficile aggirare gli errori che Scala insiste nel fare, apparentemente per ragioni a cui ho forti obiezioni. Cioè, la soluzione a "le irresponsabili obiezioni del programmatore medio (cioè troppo difficile!)" Non è "placarle per renderle più facili", ma piuttosto fornire indicazioni e assistenza per diventare programmatori migliori. Io e gli obiettivi di Scala sono in discussione su questo tema, ma torniamo al punto.

Probabilmente stavi esprimendo il tuo punto, predicendo risposte specifiche da "il programmatore medio". Cioè, le persone che reclameranno "ma è troppo complicato!" o alcuni di questi. Queste sono le Yegges o le Bloch a cui ti riferisci. La mia risposta a queste persone del movimento anti-intellettualismo / pragmatismo è piuttosto dura e sto già anticipando una raffica di risposte, quindi la ometterò.

Spero davvero che le biblioteche Scala migliorino, o almeno, che gli errori possano essere nascosti in un angolo. Java è un linguaggio in cui "tentare di fare qualcosa di utile" è così incredibilmente costoso, che spesso non ne vale la pena perché la quantità schiacciante di errori semplicemente non può essere evitata. Imploro Scala per non seguire la stessa strada.


3
Ciao Tony, grazie per il tuo contributo premuroso qui. Vorrei fare 2 risposte ad esso. Il primo è che non ho menzionato il "programmatore medio" e non credo che Scala sia necessariamente indirizzato a uno. Che sia presuntuoso o meno, credo di essere al di sopra della media; tuttavia, sento ancora che la firma del tipo sia scoraggiante! Temo ancora, in altre parole, che i programmatori sopra la media, il mercato target di Scala, possano essere scacciati.
oxbow_lakes,

6
Il secondo punto è che io fondamentalmente d'accordo con te su ciò che Scala è : Scala è un linguaggio pragmatico - non un teorico puro. Perché altrimenti sarebbe stato progettato in cima alla JVM? Questa è una decisione puramente pragmatica - è rivolta agli sviluppatori "nel mondo reale" - una scelta che potrebbe aver richiesto compromessi! Nota anche che Bloch e Yegge sono lontani dalla media dei programmatori, ma questo è il mio punto. Anche le persone molto rispettate e intelligenti possono avere opinioni sulla complessità e sulla purezza che differiscono dalla tua. Sfortunatamente per te, sono anche molto influenti.
oxbow_lakes,

3
Ciao oxbow_lakes, è uno degli obiettivi dichiarati di Scala di placare i programmatori tipici, anche a scapito dell'accuratezza e della praticità. I programmatori sopra la media vengono scacciati (ho diversi aneddoti), ma non perché le firme dei tipi siano scoraggianti, ma a causa della natura di alcuni errori. Non ho detto che Scala sia o non sia pragmatica o teorica. Inoltre, non sottoscrivo nemmeno l'idea (comune?) Dell'esistenza di una tale dicotomia. Le librerie Scala hanno rovinato la firma della mappa. Ho lavorato per anni sugli errori di Scala; in particolare le biblioteche. È ora di farlo di nuovo.
Tony Morris,

5
Non considero Bloch o Yegge molto rispettati o intelligenti, ma sono davvero piuttosto influenti. Sì, questo è sfortunato.
Tony Morris,

9
Perché riferisci l'attraversamento alla firma estesa di Scala? La mappa di Scala, per monofunctor, è la fmap standard. Ma né BitSet né Map [A, B] sono monofunctor, tuttavia map ha su di essi una definizione significativa. Questa è la motivazione della firma di Scala e la traversata non risolve questo problema. Perché la generalità è una cosa negativa? I funzioni applicative tengono traccia degli effetti, qual è il loro punto in Scala? Infine, credo che la mappa generica di Scala possa essere implementata in termini di una traversata generalizzata, accettando un CanBuildFrom e restituendo un Traversable potenzialmente diverso: non c'è bisogno di sacrificarsi per comprendere!
Blaisorblade,

15

Sono totalmente d'accordo sia con la domanda che con la risposta di Martin :). Anche in Java, leggere javadoc con i generici è molto più difficile di quanto dovrebbe essere a causa del rumore extra. Ciò è accentuato in Scala, dove vengono utilizzati parametri impliciti come nel codice di esempio delle domande (mentre gli impliciti fanno cose molto utili per il morphing delle raccolte).

Non penso che sia un problema con il linguaggio in sé - penso che sia più un problema di utensili. E mentre sono d'accordo con quello che dice Jörg W Mittag, penso che guardando scaladoc (o la documentazione di un tipo nel tuo IDE) - dovrebbe richiedere il minor potere cerebrale possibile per capire quale sia un metodo, cosa richiede e ritorna. Non dovrebbe essere necessario hackerare un po 'di algebra su un po' di carta per ottenerlo :)

Di sicuro gli IDE hanno bisogno di un modo carino per mostrare tutti i metodi per qualsiasi variabile / espressione / tipo (che come nell'esempio di Martin può avere tutti i generici incorporati, quindi è bello e facile da grok). Mi piace l'idea di Martin di nascondere anche gli impliciti per impostazione predefinita.

Per fare l'esempio in scaladoc ...

def map[B, That](f: A => B)(implicit bf: CanBuildFrom[Repr, B, That]): That

Quando guardo questo in scaladoc, vorrei che il blocco generico [B, Quello] fosse nascosto per impostazione predefinita, così come il parametro implicito (forse mostrano se si passa con il mouse su una piccola icona con il mouse) - come roba extra da grok leggendolo che di solito non è così rilevante. es. immagina se questo sembrava ...

def map(f: A => B): That

bello, chiaro ed evidente cosa fa. Potresti chiederti cosa sia "Quello", se passi il mouse o fai clic su di esso, potresti espandere il testo [B, Quello] evidenziando ad esempio "Quello".

Forse una piccola icona potrebbe essere usata per la dichiarazione [] e il blocco (implicito ...), quindi è chiaro che ci sono piccoli frammenti dell'istruzione crollata? È difficile usare un token per questo, ma userò a. per adesso...

def map.(f: A => B).: That

Quindi, per impostazione predefinita, il "rumore" del sistema di tipi è nascosto dall'80% principale di ciò che la gente deve guardare - il nome del metodo, i suoi tipi di parametri e il suo tipo di ritorno in un modo semplice e conciso - con piccoli collegamenti espandibili ai dettagli se ti interessa davvero tanto.

Per lo più le persone leggono scaladoc per scoprire quali metodi possono chiamare su un tipo e quali parametri possono passare. Stiamo sovraccaricando gli utenti con troppi dettagli proprio come IMHO.

Ecco un altro esempio ...

def orElse[A1 <: A, B1 >: B](that: PartialFunction[A1, B1]): PartialFunction[A1, B1]

Ora se nascondiamo la dichiarazione generica è più facile da leggere

def orElse(that: PartialFunction[A1, B1]): PartialFunction[A1, B1]

Quindi, se la gente passa il mouse sopra, diciamo, A1, potremmo mostrare che la dichiarazione di A1 è A1 <: A. I tipi covarianti e controversi nei generici aggiungono anche molto rumore che può essere reso in modo molto più facile da grok agli utenti, penso.


5
Ma cosa significa "Quello" come tipo di risultato?
Blaisorblade,

11

Non so come dirtelo, ma ho un dottorato di ricerca di Cambridge e sto usando 2.8 bene.

Più seriamente, non ho quasi mai trascorso un po 'di tempo con 2.7 (non interagirà con una libreria Java che sto usando) e ho iniziato a usare Scala poco più di un mese fa. Ho una certa esperienza con Haskell (non molto), ma ho semplicemente ignorato le cose di cui ti preoccupi e ho cercato metodi che corrispondessero alla mia esperienza con Java (che uso per vivere).

Quindi: sono un "nuovo utente" e non sono stato rimandato - il fatto che funzioni come Java mi ha dato abbastanza sicurezza per ignorare i bit che non capivo.

(Tuttavia, il motivo per cui stavo guardando Scala era in parte per vedere se spingerlo al lavoro, e non lo farò ancora. Rendere la documentazione meno intimidatoria sarebbe sicuramente di aiuto, ma ciò che mi ha sorpreso è quanto è ancora cambiare ed essere sviluppato (per essere onesti ciò che mi ha sorpreso di più è stato quanto è fantastico, ma i cambiamenti sono arrivati ​​un secondo vicino). Quindi immagino che ciò che sto dicendo sia che preferirei che le risorse limitate fossero impiegate per ottenerlo uno stato finale - non credo che si aspettassero di essere così popolari così presto.)


22
Penso che voglia sapere se le persone senza dottorato di ricerca di Cambridge sono in grado di gestire Scala 2.8.
Ken Bloom,

2
Haha: touche! Bene, ho detto che scala 2.8 è facile da usare - la mia domanda era più su come sarebbe stata per qualcuno che navigava nell'API per vedere se gli piaceva, supponendo che non avessero avuto esperienze precedenti in Scala.
oxbow_lakes,

1
@andrew - dall'aspetto del tuo sito web ( acooke.org ), non sei a disagio con i concetti visivamente intimidatori
oxbow_lakes,

Chiunque sia impegnato nella programmazione di Malbolge, anche se è "solo" Hello World, è improbabile che venga intimidito da qualcosa.
Carl Smotricz,

10

Non conosco affatto Scala, tuttavia poche settimane fa non riuscivo a leggere Clojure. Ora posso leggerne la maggior parte, ma non posso ancora scrivere nulla oltre gli esempi più semplicistici . Sospetto che Scala non sia diverso. Hai bisogno di un buon libro o di un corso a seconda di come impari. Leggendo la dichiarazione della mappa sopra, ne ho forse 1/3.

Credo che i problemi maggiori non siano la sintassi di questi linguaggi, ma l'adozione e l'interiorizzazione dei paradigmi che li rendono utilizzabili nel codice di produzione di tutti i giorni. Per me Java non è stato un grande salto da C ++, che non è stato un grande salto da C, che non è stato affatto un salto da Pascal, né di base ecc ... Ma la codifica in un linguaggio funzionale come Clojure è un grande salto (per io comunque). Immagino che in Scala puoi programmare in stile Java o Scala. Ma in Clojure creerai un bel pasticcio cercando di mantenere le tue abitudini imperative da Java.


5
Non si tratta mai di notazione (o mai più del 10-15% sulla notazione), riguarda sempre i concetti. E se sei ragionevolmente intelligente e non sei impantanato in decenni di conoscenza da modelli diversi, forse contraddittori (come probabilmente sono io), di solito non è difficile capire queste cose. Ma se sei intriso di un modo di pensare e fare le cose, allora è almeno un certo sforzo di adattamento e molti reagiscono contro tali cambiamenti. È solo psicologia / natura umana. (Mi chiedo come la psicologia della programmazione informatica di Weinberg regge dopo quasi 40 anni?)
Randall Schulz,

1
@Randall Schultz e Jeff G: la sintassi / notazione è ragionevolmente facile da gestire per una persona intelligente. Nomi diversi per gli stessi concetti, in sostanza. Raggiungere la velocità in una nuova lingua è solo una questione di pratica. TUTTAVIA, il passaggio dalla programmazione procedurale a quella funzionale è ... spaventosamente ampio. È davvero un modo diverso di pensare. Mi diletto con Clojure da alcuni mesi e lo trovo un linguaggio FP relativamente "facile e divertente". Ma ho ancora bisogno di quantità eccessive di tempo per scoprire cose che sarebbero semplici nella programmazione procedurale.
Carl Smotricz,

7

Scala ha molte caratteristiche folli (in particolare per quanto riguarda i parametri impliciti) che sembrano molto complicate e accademiche, ma sono progettate per rendere le cose facili da usare. I più utili ottengono zucchero sintattico (come il [A <% B]che significa che un oggetto di tipo A ha una conversione implicita in un oggetto di tipo B) e una spiegazione ben documentata di ciò che fanno. Ma la maggior parte delle volte, come cliente di queste librerie, puoi ignorare i parametri impliciti e fidarti di loro per fare la cosa giusta.


Sì, la sintassi della vista rende le cose più veloci da comprendere.
egaga,

6

Questo scoraggerà le persone a venire alla Scala?

Non penso che sia il fattore principale che influenzerà la popolarità di Scala, perché Scala ha molta potenza e la sua sintassi non è così estranea a un programmatore Java / C ++ / PHP come Haskell, OCaml, SML, Lisps, eccetera..

Ma penso che la popolarità di Scala crescerà al di sotto di quella di Java oggi, perché penso anche che il prossimo linguaggio tradizionale debba essere molto semplificato, e l'unico modo che vedo per arrivarci è la pura immutabilità, cioè dichiarativa come HTML, ma Turing completa . Tuttavia, sono di parte perché sto sviluppando un linguaggio del genere, ma l'ho fatto solo dopo aver escluso uno studio di diversi mesi che Scala non poteva bastare per quello di cui avevo bisogno.

Questo darà alla Scala un brutto nome nel mondo commerciale come un giocattolo accademico che solo gli studenti di dottorato dedicati possono capire? I CTO e i responsabili del software si spaventeranno?

Non credo che la reputazione di Scala soffrirà del complesso di Haskell. Ma penso che alcuni rimanderanno l'apprendimento, perché per la maggior parte dei programmatori, non vedo ancora un caso d'uso che li costringe a usare Scala e procrastineranno l'apprendimento. Forse il lato server altamente scalabile è il caso d'uso più convincente.

E, per il mercato principale, il primo apprendimento di Scala non è una "boccata d'aria fresca", in cui si scrivono immediatamente programmi, come ad esempio il primo utilizzo di HTML o Python. Scala tende a crescere su di te, dopo aver appreso tutti i dettagli su cui ci si imbatte fin dall'inizio. Tuttavia, forse se avessi letto Programmazione alla Scala dall'inizio, la mia esperienza e opinione sulla curva di apprendimento sarebbero state diverse.

La riprogettazione della biblioteca è stata un'idea sensata?

Decisamente.

Se stai usando Scala commercialmente, sei preoccupato per questo? Stai pianificando di adottare immediatamente 2.8 o aspetti di vedere cosa succede?

Sto usando Scala come piattaforma iniziale della mia nuova lingua. Probabilmente non starei costruendo il codice sulla biblioteca della collezione di Scala se usassi Scala commercialmente altrimenti. Vorrei creare la mia biblioteca basata sulla teoria delle categorie, dal momento che una volta ho guardato, ho trovato le firme dei tipi di Scalaz ancora più dettagliate e ingombranti della biblioteca della collezione di Scala. Parte di quel problema forse è il modo in cui Scala implementa le classi di tipo, e questa è una delle ragioni minori per cui sto creando la mia lingua.


Ho deciso di scrivere questa risposta, perché volevo costringermi a ricercare e confrontare il design della classe di collezione di Scala con quello che sto facendo per la mia lingua. Potrei anche condividere il mio processo di pensiero.

L'utilizzo da parte della collezione 2.8 di un'astrazione da costruttore è un valido principio di progettazione. Voglio esplorare due compromessi di progettazione di seguito.

  1. CODICE SOLO SCRITTURA: dopo aver scritto questa sezione, ho letto il commento di Carl Smotricz che concorda con quello che mi aspetto sia il compromesso. I commenti di James Strachan e davetron5000 concordano sul fatto che il significato di That (non è nemmeno quello [B]) e il meccanismo dell'implicito non è facile da comprendere intuitivamente. Vedi il mio uso del monoide nel numero 2 di seguito, che penso sia molto più esplicito. Il commento di Derek Mahar riguarda la scrittura di Scala, ma la lettura della Scala di altri che non è "nei casi comuni".

    Una critica che ho letto su Scala, è che è più facile scriverlo, che leggere il codice che altri hanno scritto. E trovo che ciò sia occasionalmente vero per vari motivi (ad es. Molti modi per scrivere una funzione, chiusure automatiche, Unità per DSL, ecc.), Ma sono indeciso se questo è un fattore importante. Qui l'uso di parametri di funzione implicita ha vantaggi e svantaggi. Tra i lati positivi, riduce la verbosità e automatizza la selezione dell'oggetto builder. In Odersky di esempiola conversione da un BitSet, ovvero Set [Int], a Set [String] è implicita. Il lettore non familiare del codice potrebbe non sapere facilmente quale sia il tipo di raccolta, a meno che non riescano a ragionare bene su tutti i potenziali candidati builder impliciti invisibili che potrebbero esistere nell'ambito del pacchetto corrente. Naturalmente, il programmatore esperto e lo scrittore del codice sapranno che BitSet è limitato a Int, quindi una mappa su String deve essere convertita in un diverso tipo di raccolta. Ma quale tipo di raccolta? Non è specificato esplicitamente.

  2. DESIGN DELLA COLLEZIONE AD-HOC: Dopo aver scritto questa sezione, ho letto il commento di Tony Morris e mi sono reso conto che sto facendo quasi lo stesso punto. Forse la mia esposizione più dettagliata chiarirà il punto.

    In "Combattere la putrefazione dei bit con i tipi" Odersky & Moors, vengono presentati due casi d'uso. Sono la limitazione di BitSet agli elementi Int e Map per accoppiare gli elementi tupla e sono forniti come motivo per cui la funzione di mappatura generale degli elementi, A => B, deve essere in grado di creare tipi di raccolta di destinazioni alternative. Tuttavia, questo è imperfetto dal punto di vista della teoria delle categorie. Per essere coerenti nella teoria delle categorie e quindi evitare casi angolari, questi tipi di raccolta sono funzioni, in cui ogni morfismo, A => B, deve mappare tra oggetti nella stessa categoria di funzioni, Elenco [A] => Elenco [B], BitSet [A] => BitSet [B]. Ad esempio, un'opzione è un functor che può essere visualizzato come una raccolta di insiemi di alcuni Some (oggetto) e Nessuno. Non esiste una mappa generale da None di Option, o Zero di List, ad altri funzioni che non

    C'è una scelta di design di compromesso fatta qui. Nel design per la libreria delle collezioni del mio nuovo linguaggio, ho scelto di rendere tutto un funzione, il che significa che se implemento un BitSet, deve supportare tutti i tipi di elementi, utilizzando una rappresentazione interna del campo non bit quando viene presentato con un non- parametro di tipo intero e quella funzionalità è già nel Set da cui eredita in Scala. E Map nel mio progetto deve mappare solo i suoi valori e può fornire un metodo separato non funzionale per mappare le sue tuple (chiave, valore). Un vantaggio è che ogni funzione è quindi di solito anche un applicativo e forse anche una monade. Pertanto, tutte le funzioni tra i tipi di elementi, ad es. A => B => C => D => ..., vengono automaticamente portate alle funzioni tra i tipi applicativi sollevati, ad es. Elenco [A] => Elenco [B] => Elenco [ C] => Elenco [D] => .... Per il mapping da un funzione a un'altra classe di raccolta, offro un sovraccarico della mappa che accetta un monoid, ad esempio Nil, None, 0, "", Array (), ecc. Quindi la funzione di astrazione del builder è il metodo append di un monoid e viene fornito esplicitamente come parametro di input necessario, quindi senza conversioni implicite invisibili. (Tangente: questo parametro di input consente anche di aggiungere monoidi non vuoti, cosa che il design della mappa di Scala non può fare.) Tali conversioni sono una mappa e una piega nello stesso passaggio di iterazione. Fornisco anche un attraversabile, nel senso della categoria, "Programmazione applicativa con effetti" McBride & Patterson, che consente anche map + fold in un singolo passaggio di iterazione da qualsiasi attraversabile a qualsiasi applicativo, in cui quasi tutte le classi di raccolta sono entrambe.

    Quindi gli afaici delle collezioni Scala sono "ad-hoc", nel senso che non è fondato sulla teoria delle categorie, e la teoria delle categorie è l'essenza della semantica denotazionale di livello superiore. Sebbene i costruttori impliciti di Scala siano alla prima apparizione "più generalizzati" di un modello di funzione + costruttore monoide + attraversabile -> applicativo, non hanno dimostrato di essere coerenti con nessuna categoria, e quindi non sappiamo quali regole seguano nel il senso più generale e quali saranno i casi angolari non possono obbedire a nessun modello di categoria. Semplicemente non è vero che l'aggiunta di più variabili rende qualcosa di più generale, e questo è stato uno dei grandi vantaggi della teoria delle categorie in quanto fornisce regole per mantenere la generalità mentre si solleva a semantica di livello superiore. Una collezione è una categoria.

    Ho letto da qualche parte, penso che fosse Odersky, come un'altra giustificazione per il design della biblioteca, è che la programmazione in uno stile funzionale puro ha il costo di ricorsione limitata e velocità in cui non viene utilizzata la ricorsione della coda. Non ho trovato difficile ricorrere alla ricorsione della coda in tutti i casi che ho riscontrato finora.


Inoltre, mi viene in mente un'idea incompleta che alcuni dei compromessi di Scala sono dovuti al tentativo di essere un linguaggio mutevole e immutabile, a differenza, ad esempio, di Haskell o del linguaggio che sto sviluppando. Ciò è in accordo con il commento di Tony Morris per la comprensione. Nella mia lingua, non ci sono anelli né costrutti mutabili. Il mio linguaggio siederà in cima a Scala (per ora) e gli deve molto, e questo non sarebbe possibile se Scala non avesse il sistema di tipi generali e la mutabilità. Questo potrebbe non essere vero, perché penso che Odersky & Moors ("Combattere la rotazione dei bit con i tipi") non sono corretti nel dichiarare che Scala è l'unico linguaggio OOP con tipi più alti, perché ho verificato (io stesso e tramite Bob Harper) che Standard ML li ha. Sembra inoltre che il sistema di tipi di SML possa essere equivalentemente flessibile (dagli anni '80), che potrebbe non essere facilmente apprezzato perché la sintassi non è molto simile a Java (e C ++ / PHP) come Scala. In ogni caso, questa non è una critica a Scala, ma piuttosto un tentativo di presentare un'analisi incompleta dei compromessi, che spero sia germano alla domanda. Scala e SML non soffrono dell'incapacità di Haskell di farloeredità multipla di diamanti , che è fondamentale e capisco perché molte funzioni del Preludio di Haskell vengano ripetute per diversi tipi.


Quindi, la tua lingua sarà orientata agli oggetti?
missingfaktor,

Sì, eredita il sistema di tipi di Scala. Una distinzione chiave è il tratto è suddiviso in interfaccia e mixin, in cui l'interfaccia contiene solo le firme dei metodi e nessuna implementazione. E solo un'interfaccia può essere indicata come un tipo. Gli impliciti vengono eliminati e le classi di tipi vengono gestite in modo SPOT nell'interfaccia. Ecco una bozza di dettagli. I collaboratori sono i benvenuti. Un po 'di codice per la libreria è qui . Si tratta di lavori in corso, scuse per la menzione del vaporware. Sto solo condividendo i pensieri.
Shelby Moore III,

5

Sembra necessario dichiarare qui una laurea: laurea in scienze politiche e laurea in informatica.

Al punto:

Questo scoraggerà le persone a venire alla Scala?

Scala è difficile, perché il suo paradigma di programmazione sottostante è difficile. La programmazione funzionale spaventa molte persone. È possibile creare chiusure in PHP ma le persone raramente lo fanno. Quindi no, non questa firma, ma tutto il resto rimanderà le persone, se non hanno l'istruzione specifica per farle apprezzare il potere del paradigma sottostante.

Se questa istruzione è disponibile, tutti possono farlo. L'anno scorso ho costruito un computer per scacchi con un gruppo di ragazzi delle scuole in SCALA! Hanno avuto i loro problemi ma alla fine hanno fatto bene.

Se stai usando Scala commercialmente, sei preoccupato per questo? Stai pianificando di adottare immediatamente 2.8 o aspetti di vedere cosa succede?

Non sarei preoccupato.


4

Ho una laurea in matematica anche a Oxford! Mi ci è voluto un po 'per "ottenere" le nuove collezioni. Ma mi piace molto ora che lo faccio. In effetti, la digitazione di 'map' è stata una delle prime grandi cose che mi ha infastidito in 2.7 (forse poiché la prima cosa che ho fatto è stata la sottoclasse di una delle classi di raccolta).

La lettura dell'articolo di Martin sulle nuove raccolte 2.8 ha davvero aiutato a spiegare l'uso degli impliciti, ma sì la documentazione stessa ha sicuramente bisogno di fare un lavoro migliore per spiegare il ruolo di diversi tipi di impliciti all'interno delle firme dei metodi delle API di base.

La mia preoccupazione principale è più questa: quando uscirà 2.8? Quando cesseranno le segnalazioni di bug? scala team ha morso più di quanto possa masticare con 2.8 / ha provato a cambiare troppo in una volta?

Mi piacerebbe davvero vedere 2.8 stabilizzato per il rilascio come una priorità prima di aggiungere qualsiasi altra novità, e mi chiedo (mentre guardo da margine) se alcuni miglioramenti potrebbero essere fatti al modo in cui viene gestita la roadmap di sviluppo per il compilatore scala.


-1

Che dire dei messaggi di errore nel sito d'uso?

E per quanto riguarda il caso d'uso, è necessario integrare i tipi esistenti con uno personalizzato adatto a una DSL. Bisogna essere ben educati su questioni di associazione, precedenza, conversioni implicite, parametri impliciti, tipi superiori e forse tipi esistenziali.

È molto bello sapere che per lo più è semplice ma non è necessariamente sufficiente. Almeno ci deve essere un ragazzo che conosce queste cose se si vuole progettare una biblioteca diffusa.


Ma uno dei punti principali è la differenza tra la libreria dal punto di vista di un utente e i creatori. Ovviamente i creatori hanno bisogno di una comprensione impressionante delle funzionalità linguistiche richieste (ad es. Tipi di tipo superiore, precedenza implicita) - la domanda è: "gli utenti?"
oxbow_lakes
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.