Quali sono i vantaggi e gli svantaggi negli approcci di C #, Java e Scala to Closures / Lambdas / ...?


30

Mi chiedo quali siano le differenze tecniche di implementazione tra C # e Scala e come entrambe le soluzioni si confrontino con le idee e le preoccupazioni di implementazione espresse nell'e-mail Peek Past lambda di Brian Goetz, inviata alla mailing list di Project Lambda (JSR 335) ?

Dall'email:

Abbiamo esplorato la strada di "forse i lambda dovrebbero essere solo istanze di classe interiore, sarebbe davvero semplice", ma alla fine siamo arrivati ​​alla posizione di "le funzioni sono una direzione migliore per il futuro del linguaggio".

e inoltre:

La visione lambda-sono-oggetti del mondo è in conflitto con questo possibile futuro. La visione del mondo delle lambda-sono-funzioni no, e preservare questa flessibilità è uno dei punti a favore del non appesantire le lambda con persino l'apparenza di oggettività.

Conclusione:

Lambdas-are-funzioni apre le porte. Lambdas-are-oggetti li chiude.
Preferiamo vedere quelle porte lasciate aperte.

E alcuni commenti di una persona sul thread di Reddit dicono:

In realtà ho inviato un'e-mail a Neal Gafter su questo e alla mia limitata comprensione della sua spiegazione C # e l'attuale progetto Java sono abbastanza simili in quanto i delegati sono in realtà oggetti e non tipi di funzioni. Sembra che crede che Java dovrebbe imparare dagli svantaggi degli lambda di C # ed evitarli (proprio come C # ha imparato dagli svantaggi di Java e li ha evitati all'inizio).

Perché l'approccio "Lambdas-are-funzioni" offre più opportunità in futuro rispetto a "Lambdas-are-object"? Qualcuno può spiegare quali differenze esistono e come influenzerebbero la scrittura del codice?

Vedendo che alla Scala le cose "funzionano", continuo a pensare che mi manca qualcosa degli approcci adottati / proposti in C # / Java (8), probabilmente è correlato a preoccupazioni sulla retrocompatibilità?


1
Questo è interessante. Dato che il sistema di tipi Javas non ha al momento il concetto di funzioni, ciò significherebbe che bisogna prima introdurre questo. Potrebbe essere possibile che la lingua diventi troppo complessa con questo.
Ingo,

Le funzioni non dovrebbero istanze di qualche interfaccia? Cosa c'è di così speciale in loro?
soc,

Lisp / Scheme / Clojure può modellare oggetti mentre Java / C # non può modellare l'annidamento arbitrario di funzioni. Python sembra avere il meglio di entrambi i mondi, tuttavia.
Giobbe

Risposte:


15

Penso che la discussione sugli oggetti contro le funzioni sia un'aringa rossa. Se la domanda è: "Una lambda è una funzione o un oggetto?" la risposta dovrebbe essere .

Questo è il punto delle funzioni di prima classe: non sono trattate in modo diverso rispetto a qualsiasi altro tipo. Java riesce già a ignorare principalmente le differenze tra Object e tipi primitivi (e Scala lo fa ancora meglio), quindi se una lambda è una sottoclasse di Object o è un nuovo tipo primitivo o qualcos'altro non è davvero importante per il linguaggio. Ciò che è importante è che puoi mettere i tuoi lambda in raccolte, passarli in giro per essere chiamati, chiamarli e fare qualsiasi altra cosa che potresti voler fare con un oggetto o un metodo.

Scala realizza questo usando un oggetto wrapper che ha un metodo chiamato applyche può essere invocato solo (), facendolo apparire come una chiamata di metodo. Funziona magnificamente; la maggior parte delle volte non è nemmeno necessario preoccuparsi se si dispone di un metodo o si sta chiamando l'applicazione di un oggetto funzione.


9

Da quello che ho capito, è più su come gli lambda sono considerati a livello di lingua primaria. Come dice l'e-mail,

Potresti pensare che il design attuale sia strettamente legato a una scatola di oggetti per lambda - tipi SAM - rendendoli comunque oggetti efficaci. Ma questo è stato accuratamente nascosto dalla superficie in modo da permetterci di considerare lambda "nudi" in futuro, o considerare altri contesti di conversione per lambda, o integrare lambda più strettamente nei costrutti di controllo. Non lo stiamo facendo ora e non abbiamo nemmeno un piano concreto per farlo, ma la possibilità di farlo in futuro è una parte fondamentale del progetto.

Penso che riassuma abbastanza bene la tua domanda. Se dichiari che "i lambda sono oggetti", allora sono solo un oggetto di una particolare classe e ne sei bloccato. D'altra parte, se dichiari "le lambda sono funzioni", allora semanticamente hai un campo da gioco molto più ricco. Java 1.7 potrebbe compilarli in oggetti, quindi sono praticamente identici a quel punto.

Ma Java 1.8, o 1.9, potrebbe apportare modifiche al linguaggio (come tipi strutturali reificati) piuttosto che consentire alle funzioni di essere utilizzate in modi molto più flessibili. Se "lambda fosse un oggetto", questi cambiamenti non sarebbero compatibili con le versioni precedenti e dovresti introdurre un nuovo concetto oltre, in modo da non violare il codice esistente delle persone. Ma se javacstava semplicemente convertendo lambda in oggetti dietro le quinte, il nuovo javacpuò convertirli in qualsiasi cosa voglia, purché la semantica sia ancora valida.


lamdas in C #! = dai delegati. Il compilatore ha la possibilità di compilarli in delgate o alberi delle espressioni. entrambi sono effettivamente grafici a oggetti ma non sono compilati in una "classe particolare" e neppure in una classe di un albero ereditario particolare
Rune FS

Se ho capito bene, quindi compilando il lambda in una classe interna dell'oggetto a cui è associato lo lega a quell'oggetto, quindi in futuro se Java dovesse introdurre funzioni di ordine superiore (funzioni allo stesso livello di oggetti) allora tu non è stato possibile utilizzare l'implementazione della classe interna e ci sarebbe un'incoerenza. Non credo che Java avrà presto funzioni di ordine superiore.
mwolfetech,

@mwolfetech: per quanto ne so, sono già previsti per Java 8 con metodi di difesa. Vogliono aggiungere cose come foreach, map, filteralle collezioni.
soc,

@soc Un buon punto, è difficile tenere il passo con il numero di JSR e se effettivamente completeranno e realizzeranno una versione target di JDK. Sembra che i metodi di difesa possano far parte dello stesso JSR. Per quanto riguarda questo JSR , ho trovato utile il post sullo stato di Lambda di Brian Goetz - spiega i tipi di SAM e i pensieri attuali per l'implementazione delle espressioni lambda.
mwolfetech,

"pensieri attuali" mhhh, quel post del 2010 non è ormai obsoleto?
soc,

5

Per lo più, semplicemente non vuole impegnarsi troppo presto per qualcosa. Non vedo alcun motivo oltre quello della cancellazione che ha presentato, ma questa è davvero una ragione molto forte.

Non mi piacciono i tipi di funzione - adoro i tipi di funzione - ma quei tipi di funzioni hanno combattuto male con un aspetto esistente del sistema di tipi Java, la cancellazione. I tipi di funzione cancellati sono i peggiori di entrambi i mondi.

Considera questi metodi in Scala Regex:

def replaceAllIn (target: CharSequence, replacer: (Match)  String): String
def replaceSomeIn (target: CharSequence, replacer: (Match)  Option[String]): String

Sarebbe più semplice se fossero semplicemente questi:

def replace (target: CharSequence, replacer: (Match)  String): String
def replace (target: CharSequence, replacer: (Match)  Option[String]): String

Sfortunatamente, ciò non è possibile, poiché queste due funzioni sono identiche in caso di cancellazione. Ma bene, queste funzioni fanno cose in qualche modo diverse, quindi un nome diverso potrebbe essere abbastanza giusto.

Tuttavia, a Matchè qualcosa di molto utile, ma il più delle volte si desidera sia Stringl'elenco corrispondente che l'elenco dei sottogruppi. Vorremmo avere questo:

def replaceAllIn (target: CharSequence, replacer: (String)  String): String
def replaceAllIn (target: CharSequence, replacer: (Seq[String])  String): String
def replaceAllIn (target: CharSequence, replacer: (Match)  String): String

Impossibile, a causa della cancellazione. Ho scelto questo esempio particolare perché ne sono stato direttamente coinvolto, ma ho visto almeno una mezza dozzina di domande su Stack Overflow, in cui le persone chiedono perché un sovraccarico è illegale, causato da questo esatto problema.

E, quindi, considera che la corrispondenza dei modelli di Scala e Java instanceofsono effettivamente inutili a causa della cancellazione.

Penso che sia giusto ritardare i tipi di funzione fino a quando questo problema non verrà risolto. Dopotutto, ci sono molti linguaggi che lo hanno sulla JVM e non è come se Java fosse un linguaggio in rapida evoluzione.


Bene, se la cancellazione del tipo è l'unico problema che hanno, cosa hanno intenzione di fare? La violazione di ogni codice su questo pianeta era già stata dichiarata non opzionale per Java 5 ...
soc

@soc Sono così felice di non essere nei loro panni! Ma quello era Sun, questo è Oracle. Oracle non ha mai avuto alcun complimento nel fare le modifiche di rottura tra le versioni principali - e anche minori - del suo prodotto principale.
Daniel C. Sobral,

Forse dovrebbero cambiare il nome della lingua e iniziare a sviluppare una nuova lingua, abbandonando la compatibilità con le versioni precedenti. Quindi uno avrebbe i vantaggi di una nuova lingua senza la necessità di giocare con una lingua più vecchia e consolidata. Dopotutto, è quello che hanno fatto Scala e Clojure.
Giorgio,

@Giorgio Sarebbe un po 'inutile. Bene, alcune delle persone che sono responsabili di ciò che Java è oggi hanno fatto, ma, come hai detto, ci sono alternative. Ma le persone responsabili di Java devono migliorare Java stesso - dopo tutto sono responsabili di esso. L'unica alternativa è semplicemente rilasciare Java e rinunciare a tutti i vantaggi derivanti dal suo controllo.
Daniel C. Sobral,

@Daniel C. Sobral: IMO un linguaggio di programmazione è un po 'come un software: all'inizio può essere pulito e ben progettato, ma più ci giochi e più diventa disordinato. Quindi penso che sarebbe nell'interesse degli sviluppatori congelare Java come lingua e concentrare lo sviluppo sulla (1) creazione di nuove librerie o sul miglioramento di quelle esistenti, (2) sul miglioramento della JVM (se possibile), (3) sullo sviluppo di nuove lingue . Ma come hai detto, ci sono persone responsabili di Java e che vogliono continuare a vendere aggiornamenti. Quindi lo estenderanno per mantenerlo "fresco". Solo i miei 2 centesimi.
Giorgio,
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.