2010-11-29 18 views
9

Il compilatore Scala compila direttamente il codice byte Java (o .NET CIL). Alcune delle funzionalità di Scala potrebbero essere rifatte in Java in modo diretto (ad esempio semplici per comprensione, classi, traduzione di funzioni anonime/interne ecc.). Quali sono le caratteristiche che non possono essere tradotte in questo modo?Quali caratteristiche di Scala non possono essere tradotte in Java?

Questo è presumibilmente per lo più di interesse accademico. Più utile, forse, quali sono le caratteristiche chiave o gli idiomi di Scala che usi che non possono essere facilmente rappresentati in Java?

C'è dell'altro? Cose che possono essere fatte direttamente in Java che non hanno un equivalente diretto in Scala? Idiomi in Java che non traducono?

+0

Buona domanda con buone risposte. Sembra che confrontando Scala con Java, la gente finalmente capisca che tutti i linguaggi sono ugualmente potenti ma offrono diverse astrazioni che hanno (dis) vantaggi diversi. – Raphael

risposta

10

Questa domanda, a mio avviso, non ci tiene al punto chiedendoci di confrontare le lingue JVM osservando il loro codice byte generato.

Scala compila al bytecode Java-equivalente. Cioè, il bytecode potrebbe essere stato generato dal codice scritto in Java. In effetti puoi anche ottenere scalac per generare un modulo intermedio che assomiglia molto a Java.

Tutte le funzioni come tratti (tramite spedizionieri statici), i rendimenti non locali (tramite eccezioni), i valori pigri (attraverso riferimenti), ecc sono tutti esprimibili da un programma Java, anche se forse in maniera più-brutto!

Ma ciò che rende Scala scala e non Java è ciò che scalac può fare per voi, prima che il bytecode viene generato. Che cosa sta facendo scalac, come una lingua tipizzata staticamente, è la capacità di controllare un programma per la correttezza, inclusa la correttezza del tipo (secondo il suo sistema di tipo ) al momento della compilazione.

La principale differenza quindi tra Java e Scala (come ovviamente Java è anche staticamente tipizzato), quindi, è il sistema tipi di Scala, che è in grado di esprimere le relazioni programmatiche che sistema del tipo di java-the-lingua non può .Per esempio:

class Foo[M[_], A](m : M[A]) 
trait Bar[+A] 

Questi concetto, che M è un parametro di tipo, che a sua volta ha parametri di tipo o che Bar è covariante, semplicemente non esistono in Java-terre.

+0

Avrei pensato che non è necessariamente il caso che tutte le possibilità di codice byte Java possano essere generate da un programma sorgente Java? Quindi ci possono essere casi in cui Scalac può generare quel javac cannnot e viceversa. –

+0

Questo è vero ma scala ha specificamente * non * preso questa rotta. Quasi tutto il byte che emette scala potrebbe essere stato emesso da un programma Java. Ma il punto fondamentale è che non sono i * byte * che definiscono scala e che scala può fare per te –

+0

concordato. Sono curioso delle differenze, nondimeno (Contesto: conosco (molto) poco Java e sto imparando Scala. Mi piace quello che conosco finora su Scala, ma mi chiedo quanta frustrazione mi stia preparando per quando tornare a Java. È come quando ho imparato Lisp - che ha cambiato il modo in cui ho scritto in tutte le lingue, ma alcune cose in Lisp sono quasi impossibili in linguaggi come C. –

11

I tratti sono una cosa che non ha un equivalente. I tratti sono interfacce con il codice in loro. Puoi copiare il codice in tutte le classi che hanno un carattere misto, ma non è la stessa cosa.

Inoltre, credo che il sistema di tipo scala sia più completo. Mentre alla fine si associerà ai tipi JVM (in realtà subiscono la cancellazione). Puoi esprimere alcune cose nel sistema di tipo Scala che potrebbe non essere possibile in Java (come le varianze).

4

Penso che non ci siano equivalenti per mixare dinamicamente in alcuni Tratti. In Scala puoi aggiungere al momento della creazione di nuovi oggetti alcuni Tratti, che sono mescolati in.

Per esempio, creiamo un cane affamato e assetato e un cane affamato.

val hungryThirstyDog = new Dog with Hungry with Thirsty 
val onlyHungryDog = new Dog with Hungry 

Non conosco un modo equivalente per farlo in Java. In Java, l'ereditarietà è definita staticamente.

+0

C'è un modo per risolvere lo stesso problema di progettazione in Java, usando qualche altra tecnica? –

+0

@Paul Definisci "risolva", "facilmente rappresentato", "esprima naturalmente", ecc. Per quanto riguarda la composizione della miscela, problemi simili sono gestiti in Java usando la composizione oggetto (has-a) e l'iniezione di dipendenza, ma queste tecniche introducono dipendenze non necessarie e/o richiedere più piastre. –

+0

Non ho intenzione di definire tutti i termini. Immagino che il lettore possa interpretare. Grazie per la risposta. –

4

Le conversioni implicite non hanno un equivalente diretto in Java.

+0

Ma presumibilmente quelli espliciti potrebbero essere fatti? Quindi questa è una comodità (utile per essere sicuri) piuttosto che una differenza di espressività. Mi interessa esplorare fino a che punto Scala ti permette di esprimere le cose più "naturalmente" (per certi valori di "naturale") –

+1

Quando ci esprimiamo in linguaggio naturale, spesso elidiamo aspetti del contesto che sono dati per scontati dal Allo stesso modo, quando si programma in Scala, trovo molto naturale elidere parametri o conversioni che sono chiari dal contesto o da presupposti predefiniti –

+0

Sì, buon commento. Sto anche trovando quello su Scala . –

4

Una caratteristica di scala che ho trovato utile è la reificazione del tipo tramite Manifesti. Poiché la JVM rimuove tutte le informazioni di tipo dai generici, scala consente di conservare queste informazioni in variabili. Questo è qualcosa che la riflessione Java AFAIK non può gestire, poiché non ci sono argomenti per i tipi nel bytecode.

Il caso che mi serviva era la corrispondenza del modello su un tipo di List. Questo è, ho avuto un oggetto VertexBuffer che memorizzava i dati sulla GPU, che potevano essere costruiti da un elenco di float o interi. Il codice manifesto sembrava circa come questo:

class VertexBuffer[T](data:List[T])(implicit m:Manifest[T]) { 
    m.toString.match { 
    case "float" => ... 
    case "int" => ... 
    } 
} 

This link link ad un post sul blog con più informazioni.

Esistono molte pagine SO con ulteriori informazioni, ad esempio this one.

+0

Naturalmente, è possibile richiedere al chiamante di passare esplicitamente un 'Classe ' in Java. –

+0

O qualsiasi identificatore come un enum. Scala's è più pulito, ma immagino che non sia un'enorme differenza. – nullspace

3

Tre parole: tipi più elevati.

0

L'argomento non è chiaro, per quanto intendiamo Java la JVM o Java la lingua. Dato che Scala funziona sulla JVM, la q non ha senso, come tutti sappiamo che Scala funziona sulla JVM.

+0

Penso che sia già chiaro, ma per chiarezza intendo Java il linguaggio –

+0

Quindi per definizione è possibile esprimere qualsiasi scala di costrutto in java anche se ce n'è un sacco di boilterplate e rumoroso. –

+1

No, è vero solo se esiste un programma Java in grado di produrre tutte le sequenze bytecode valide. Non ho idea se sia vero, ma non è un dato di fatto. E ho usato la parola "straighforward" nella domanda. Java e Scala sono equivalenti in quanto entrambi sono completi di Turing, ma l'espressività, la chiarezza e così via possono differire. Questo è quello che cercavo –

Problemi correlati