Come abbiamo già detto, Scala gira sulla JVM , il codice cioè viene compilato in bytecode java eseguibile normalmente sulla macchina virtuale. Anche se non ben supportata come per la versione java esiste una versione di scala che poggia sul CLR , la macchina virtuale del framework .NET. Detto questo, mettiamo da parte .NET e da ora in poi consideriamo Scala per JVM dove non esplicitamente indicato.
Imparare una nuova sintassi può sembrare noioso e/o una perdita di tempo, la progettazione del linguaggio Scala è veramente molto accurata ed è stata effettuata tenendo in mente un principio ben preciso:
avere un set di regole sintattiche e semantiche uniformi e sempre valide che definiscano il linguaggio
in Scala è difficile trovare casi particolari, eccezioni a una regola o alle convenzioni da dovere ricordare. Scala adotta un modello a Oggetti puro e come vedremo molte delle magie sintattiche del linguaggio non sono altro che convenzioni valide per tutti gli oggetti, compresi quelli definiti dall’ utente. In questo modo un programmatore Scala ha la possibilità di scrivere librerie che è difficile distinguere dal linguaggio nativo con una potenza espressiva senza precedenti.
Cercherò di raccogliere tutte le regole più interessanti segnalandole con (*)
def valoreAssoluto(x: Double): Double = {
if (x >= 0) x
else (-x)
}
Vediamo la definizione di una funzione in Scala, proviamo a definire una funzione di valore assoluto, possiamo notare, dopo la parola chiave def e il nome della funzione, la lista dei parametri tra parentesi tonde, in questo caso il parametro della funzione x:Double e la dichiarazione del tipo di ritorno :Double, dopodiché segue il corpo della funzione tra le parentesi graffe, in cui cerchiamo invano la presenza di return, il compilatore Scala restituisce il valore dell’ ultima espressione corrispondente al tipo di ritorno, nel nostro caso x se x è non negativo e –x in caso contrario, come ci aspettiamo da una funzione valore assoluto. E’ possibile comunque inserire clausole di return esplicite , quando necessario.
Possiamo utilizzare in modo trasparente librerie Java,
import java.math._
def random: Double = java.lang.Math.random()
numeroCasualeTra1e10: Double = random * 10
notiamo che la sintassi per l’import è simile alla corrispondente in Java, il carattere jolly è in questo caso ‘_’ e non ‘*’, la motivazione come vedremo in seguito di questa differenza è da cercare nella possibilità dei nomi di metodi in Scala di contenere caratteri come ‘<’, ‘>’, ‘*’, ecc. , ma non ‘_’ .
nella seconda riga invece vediamo come sia possibile omettere il corpo del metodo tra graffe quando la funzione è costituita da una sola espressione e come sia opzionale indicare le parentesi per le funzioni che non hanno parametri, in questo caso saremo obbligati a richiamare la funzione senza parentesi, se avessimo indicato le parentesi vuote nella definizione della funzione avremmo potuto richiamarla con o senza parentesi.
(*1) – i metodi possono avere nel nome simboli <>-+*... eccetto _
(*2) – un metodo che accetta un solo parametro può utilizzare la notazione infissa.
(*3) – gli operatori sono metodi
(*4) - non esistono tipi primitivi, Int, Double, String, Char, ecc. sono tutte classi della libreria scala
analizziamo il codice
val num = 3 * 8
come abbiamo già visto in precedenza il compilatore inferisce il tipo, ma l' aspetto interessante è che l' operazione di moltiplicazione tra literals non è altro che l'equivalente di
val num = (3).*(8)
Stiamo semplicemente richiamando il metodo * sull' oggetto 3 passando come parametro l'oggetto 8 e restituisce il loro prodotto. Nel primo caso, abbiamo sfruttato la seconda regola e cioè utilizzare il metodo come operatore infisso.
(*5) - quando un metodo viene utilizzato con notazione infissa il metodo viene sempre applicato all' operando a sinistra e ha come parametro l' operando a destra, tranne quando il nome del metodo finisce per ':'. Comprenderemo meglio il perché quando esploreremo le liste in Scala.
Nessun commento:
Posta un commento