:Future[T] :T Futures val x = future { someexpensivecomputation() val y = future { someotherexpensivecomputation() val z = for (a <- x; b <- y) yield a*b for (c <- z) println("result: " + c) println("meanwhile, the main thread goes on!") 1) Hello, World! someexpensivecomp someotherexpensivecomp print( Meanwhile ) a*b print( Result +c) Hello World class HelloWorld { public static void main(string[] args){ System.out.println( Hello, World! ); uno script termina con un espressione-risultato un applicazione è un insieme di definizioni Scala interpreter: println( Hello, World! ) una shell intera/va che valuta espressioni (integrata in IDE) interpreta gli script: sequenza di istruzioni dentro un file hello.scala che eseguo con il comando > scala hello.scala Hello World class HelloWorld { public static void main(string[] args){ System.out.println( Hello, World! ); Singleton object: classe con una sola istanza object HelloWorld { def main(args: Array[String]){ println( Hello World! ) Array[T] è una classe generica No Npo di ritorno :Unit No ; Si compila il file con > scalac Hello.scala Viene prodoqo Hello.class che connene standard Java bytecode Si esegue con > scala HelloWorld
1) Hello, World! 2) Definire una classe molto semplice Una classe public class Person { public final String name; public int age; Person(String name, int age) { this.name = name; this.age = age; class Person( val name: String, var age: Int) { Immutable value read-only variable val b = new Person( Pippo,10) println(b.age) variabili: val oppure var? Due Npi di variabili: val msg = Hello world var i=0 i parametri dei metodi/funzioni sono vals i valori dei parametri non cambiano, per costruzione! i parametri sono passan per valore, come in Java Func/onal Style Ogni volta che si può, meglio usare vals, immutable variable non può essere modificata mutable variable è più facile ragionare su ciò che si è scritto! 1) Hello, World! 2) Definire una classe molto semplice 3) Dato un elenco di Persone, produrre un elenco di maggiorenni ed un elenco di minorenni
import java.util.arraylist; Person[] people = ; Lista implementata con un resizable array Person[] minors; Person[] adults; ArrayList<Person> minorslist = new ArrayList<Person>(); ArrayList<Person> adultslist = new ArrayList<Person>(); for (int i = 0; i < people.length; i++) if (people[i].age < 18) minorslist.add(people[i]); else adultslist.add(people[i]); È un metodo della classe Array[T] minors = minorslist.toarray(people); adults = adultslist.toarray(people); Restituisce un array del tipo del parametro def partition (p: T=>Boolean) : (Array[T], Array[T]) Scorre gli elementi dell array this e restituisce una coppia di array = Invocato con notazione infissa x => x.age < 18 È un pattern matching! È un metodo della classe Array[T] def partition(p: T=>Boolean):(Array[T], Array[T]) È un metodo della classe Array[T] def partition(p: T=>Boolean):(Array[T], Array[T]) i 3pi sono inferi3! È un valore funzione, def fun(x){ retrun x.age < 18 à la Ruby e Haskell un anonymous function literal scala> val prova = Array (1,2,3,4) prova: Array[Int]=Array(1,2,3,4) scala> val (x,y)=prova partition (_<2) x: Array[Int] = Array(1) y: Array[Int] = Array(2,3,4) i 3pi sono inferi3! x => x.age < 18
import java.util.arraylist; Lista implementata con un resizable array Person[] people; Person[] minors; Person[] adults; ArrayList<Person> minorslist = new ArrayList<Person>(); ArrayList<Person> adultslist = new ArrayList<Person>(); 1) Hello, World! 2) Definire una classe molto semplice for (int i = 0; i < people.length; i++) if (people[i].age < 18) minorslist.add(people[i]); else adultslist.add(people[i]); minors = minorslist.toarray(people); adults = adultslist.toarray(people); 3) Dato un elenco di Persone, produrre un elenco di maggiorenni ed un elenco di minorenni Restituisce un array del tipo del parametro 4) Cercare se in una stringa compare un caraqere maiuscolo boolean hamaiuscolo = false; boolean hamaiuscolo = false; for (int i = 0; i < name.length() &&!hamaiuscolo; i++) for (int i = 0; i < name.length() &&!hamaiuscolo; i++) if (Character.isUpperCase(name.charAt(i))) hamaiuscolo = true; if (Character.isUpperCase(name.charAt(i))) hamaiuscolo = true; String è una sequenza di caraqeri, su cui si possono testare dei predican (=funzioni che ritornano un booleano) ok, ma il metodo exists String è una sequenza di caraqeri, su cui si possono testare dei predican anche in Java (=funzioni che ritornanoèundefinibile booleano) val name : String = val name : String = x => x.isuppercase x => x.isuppercase è una struttura di controllo molto utile: prende un predicato e lo testa su tutti gli elementi della sequenza è una struttura di controllo molto utile: prende un predicato e lo testa su tutti gli elementi della sequenza
interface CharProperty { boolean hasproperty(char ch); static boolean exists (String s, CharProperty prop ) { boolean trovato = false; for (int i = 0; i < s.length() &&!trovato; i++) if (prop.hasproperty(s.charat(i))) trovato = true; return trovato; boolean hamaiuscolo = exists( name, new CharProperty(){ public boolean hasproperty(char ch){ return Character.isUpperCase(ch); ); interface CharProperty { boolean hasproperty(char ch); static boolean exists (String s, CharProperty prop ) { boolean trovato = false; for (int i = 0; i < s.length() &&!trovato; i++) la sintassi if (prop.hasproperty(s.charat(i))) per i function literal è molto leggera trovato = true; return trovato; passare funzioni è facile, immediato, naturale diventa naturale definire ed usare strutture di controllo ad hoc boolean hamaiuscolo = exists( name, new CharProperty(){ public boolean hasproperty(char ch){ return Character.isUpperCase(ch); ); Char => Boolean val name :String = Char => Boolean val name :String = interface CharProperty { boolean hasproperty(char ch); interface Predicate<T> { boolean test(t x); Predicate<Character> static boolean exists (String s, CharProperty prop ) { boolean trovato = false; for (int i = 0; i < s.length() &&!trovato; i++) if (prop.hasproperty(s.charat(i))) trovato = true; prop.test return trovato; new Predicate<Character>(){ public boolean test(character ch){ boolean hamaiuscolo = exists( name, new CharProperty(){ public boolean hasproperty(char ch){ return Character.isUpperCase(ch); ); Lambda expression exists(name, ch -> Character.isUppercase(ch)) Method Reference exists(name, Character::isUppercase) static boolean exists(string s, Predicate<Character> p){ boolean hamaiuscolo = val name :String = exists(name, ch -> Character.isUppercase(ch)) exists(name, Character::isUppercase) Lambda expression Method Reference?? name.exists(character::isuppercase) si ma solo se name ha tipo Stream! Stream.of(name).exists(Character::isUppercase)
2 s/li in 1 linguaggio Il codice Java è quasi codice Scala object Example1 { for (i <- 0 until args.length) { il 3po di b non è specificato Console.println(b.toString) for (i <- 0 until args.length) { versione scala del for args(i) invece di args[i] val range = (0).until(args.length) for (i <- range) { i 3pi sono inferi3! 0:Int è convertito a 0:RichInt che ha un metodo until che resituisce un Range
è un for con sintassi speciale assomiglia al for (i <- 0 until args.length) { for-each di Java 5 è un for con sintassi speciale for( String arg : args ) b.append(arg.touppercase); c è un for-each anche in Scala: dato args:array[string] for (i <- 0 until 10) for (i <- 0 to 10) dato String[]args: for( String arg : args ) b.append(arg.touppercase); unico for, e foreach è un metodo dato String[]args: for (x <- listaint) for (x <- listaint if x>0 ) args.foreach(arg => b.append(arg.touppercase)) metodo di Array che chiama la funzione passata su tu\ gli elemenn dell array di invocazione il tipo di arg è inferito il valore di b?? object Example1 { for (i 0 until args.length) { Console.println(b.toString) CLOSURE funzioni higher-order al posto dei loop object Example2 { println(args.map( _.touppercase ).mkstring(" ") forma un unica stringa con tutti gli elementi della sequenza di invocazione, restituisce la sequenza di invocazione in cui ha usando il parametro come separatore object Example1 { for (i 0 until args.length) { Console.println(b.toString) object Example2 { println(args.map( _.touppercase ).mkstring(" ") appilcato la funzione passata ad ogni elemento