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

30

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

Dall'email:

We explored the road of "maybe lambdas should just be inner class instances, that would be really simple", but eventually came to the position of "functions are a better direction for the future of the language".

e ulteriormente:

The lambdas-are-objects view of the world conflicts with this possible future. The lambdas-are-functions view of the world does not, and preserving this flexibility is one of the points in favor of not burdening lambdas with even the appearance of object-ness.

Conclusione:

Lambdas-are-functions opens doors. Lambdas-are-objects closes them.
We prefer to see those doors left open.

E alcuni commenti di una persona sul thread Reddit dicono:

I actually e-mailed Neal Gafter about this and to my limited understanding of his explaination C# and the current Java design are quite similar in that Delegates are actually objects and not function types. It seems like he believes that Java should learn from the disadvantages of C#'s lambdas and avoid them (much like C# learned from Java's disadvantages and avoided them in the beginning).

Perché l'approccio "Lambdas-is-functions" offre più opportunità in futuro di "Lambdas-are-objects"? Qualcuno può spiegare quali differenze esistono e come influenzerebbero il modo in cui il codice sarebbe stato scritto?

Visto che cose in Scala "funzionano", continuo a pensare che mi manchi qualcosa sugli approcci adottati / proposti in C # / Java (8), probabilmente è legato alle preoccupazioni sulla retrocompatibilità?

    
posta soc 19.08.2011 - 14:12
fonte

3 risposte

15

Penso che la discussione sugli oggetti rispetto alle funzioni sia una falsa pista. Se la domanda è: "Un lambda è una funzione o un oggetto?" la risposta dovrebbe essere si .

Questo è il punto delle funzioni di prima classe: non sono trattate diversamente da nessun altro tipo. Java già riesce a ignorare per lo più le differenze tra i tipi Object e primitive (e Scala lo fa ancora meglio), quindi se un lambda è una sottoclasse di Object o è un nuovo tipo primitivo o qualcos'altro non è veramente importante per il linguaggio. Ciò che è importante è che puoi mettere i tuoi lambda nelle raccolte, passarli per essere chiamati, chiamarli e fare qualsiasi altra cosa tu voglia fare con un oggetto o un metodo.

Scala lo fa usando un oggetto wrapper che ha un metodo chiamato apply che può essere richiamato con solo () , facendolo apparire come una chiamata di metodo. Questo funziona splendidamente; il più delle volte non ti serve nemmeno sapere se hai un metodo o stai chiamando l'applicazione di un oggetto funzione.

    
risposta data 19.08.2011 - 16:48
fonte
9

Da quanto ho capito, si tratta di come i sono considerati al livello della lingua principale. Come dice l'email,

You might think that the current design is tightly tied to an object box for lambdas -- SAM types -- making them effectively objects anyway. But this has been carefully hidden from the surface area so as to allow us to consider 'naked' lambdas in the future, or consider other conversion contexts for lambdas, or integrate lambdas more tightly into control constructs. We're not doing that now, and we don't even have a concrete plan for doing so, but the ability to possibly do that in the future is a critical part of the design.

Penso che riassuma abbastanza bene la tua domanda. Se dichiari che "lambda sono oggetti", allora sono solo un oggetto di una particolare classe e tu sei bloccato con quello. D'altra parte, se dichiari "lambdas are functions", allora semanticamente hai un campo di gioco molto più ricco. Java 1.7 potrebbe compilarli fino agli oggetti, quindi sono praticamente identici a quel punto.

Ma Java 1.8, o 1.9, potrebbero apportare modifiche al linguaggio (come i tipi strutturali reificati) piuttosto che consentire l'uso delle funzioni in modi molto più flessibili. Se "lambda fossero oggetti", queste modifiche non sarebbero retrocompatibili e dovresti introdurre un nuovo concetto alternativo, in modo da non violare il codice esistente delle persone. Ma se javac stava semplicemente convertendo tranquillamente lambda in oggetti dietro le quinte, il nuovo javac può convertirli in qualsiasi cosa desideri, a patto che la semantica rimanga valida.

    
risposta data 19.08.2011 - 14:26
fonte
5

Per lo più, non vuole impegnarsi troppo presto per qualcosa. Non vedo alcuna ragione al di là della cancellazione che ha presentato, ma questa è davvero una ragione molto strong.

I don't like function types -- I love function types -- but that function types fought badly with an existing aspect of the Java type system, erasure. Erased function types are the worst of both worlds.

Considera questi metodi in Regex di Scala:

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

Sarebbe più semplice se fossero semplicemente questo:

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

Sfortunatamente, ciò non è possibile, perché quelle due funzioni sono identiche sotto cancellazione. Ma, bene, queste funzioni fanno cose un po 'diverse, quindi un nome diverso potrebbe essere abbastanza giusto.

Tuttavia, un Match è qualcosa di molto utile, ma la maggior parte delle volte vuoi la String abbinata o l'elenco di sottogruppi. Ci piacerebbe 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

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

E, quindi, considera che la corrispondenza dei pattern di Scala e la instanceof di Java sono effettivamente inutili a causa della cancellazione.

Penso sia giusto posticipare i tipi di funzione fino a quando non viene affrontato questo problema. Dopotutto, ci sono molti linguaggi che hanno sulla JVM, e non è che Java sia un linguaggio in rapida evoluzione.

    
risposta data 19.08.2011 - 23:20
fonte

Leggi altre domande sui tag