<<

Bibliography

Analyse et Conception Formelles Programming in Scala, M. Odersky, L. Spoon, B. Venners. Artima. http://www.artima.com/pins1ed/index.html Lesson 5 An Overview of the Scala Programming Language, M. Odersky & al. http://www.scala-lang.org/docu/files/ScalaOverview.pdf – Crash Course on Scala Scala web site. http://www.scala-lang.org

Acknowledgements Many thanks to J. Noy´e and J. Richard-Foy for providing material, answering questions and for fruitful discussions.

T. Genet (ISTIC/IRISA) ACF-5 1/35 T. Genet (ISTIC/IRISA) ACF-5 2/35

Scala in a nutshell Outline “Scalable language”: small scripts to architecture of systems 1 Basics Base types and type inference Control : if and match - case Designed by Martin Odersky at EPFL Loops (for) and structures: Lists, Tuples, Maps I Programming language expert 2 Functions

I One of the designers of the Java compiler Basic functions Anonymous, Higher order functions and Partial application 3 Object Model Pure object model: only objects and method calls (=Java) ” Class definition and constructors Method/operator/function definition, overriding and implicit defs With : higher-order, pattern-matching, . . . Traits and polymorphism Fully interoperable with Java (in both directions) Singleton Objects Case classes and pattern-matching Concise smart syntax (=Java) 4 Interactions with Java ” Interoperability between Java and Scala A compiler and a read-eval-print loop integrated into the IDE 5 Isabelle/HOL export in Scala Scala worksheets!!

T. Genet (ISTIC/IRISA) ACF-5 3/35 T. Genet (ISTIC/IRISA) ACF-5 4/35 Outline Base types and type annotations 1 Basics Base types and type inference Control : if and match - case Loops (for) and structures: Lists, Tuples, Maps 1:Int, "toto":String, ’a’:Char, ():Unit 2 Functions Every data is an object, including base types! Basic functions e.g. 1 is an object and Int is its class Anonymous, Higher order functions and Partial application Every access/operation on an object is a method call! 3 Object Model e.g. 1+2executes: 1.+(2) (o.x(y) is equivalent to oxy) Class definition and constructors Method/operator/function definition, overriding and implicit defs Traits and polymorphism Exercise 1 Singleton Objects Use the max(Int) method of class Int to compute the maximum of 1+2 Case classes and pattern-matching and 4. 4 Interactions with Java Interoperability between Java and Scala 5 Isabelle/HOL export in Scala

T. Genet (ISTIC/IRISA) ACF-5 5/35 T. Genet (ISTIC/IRISA) ACF-5 6/35

Class hierarchy Hierarchy Scala’s · 11 Chapter 11.1 Section Class hierarchy

scala Subtype Any Implicit Conversion Cover · Overview scala scala scala AnyRef AnyVal ScalaObject «java.lang.Object»

scala

· Double scala Contents

Unit Hierarchy Scala’s · 11 Chapter 11.1 Section

scala scala Float scala Boolean java.lang Iterable String ·

Discuss scala scala Long Char scala Subtype Seq scala ... (other Java classes) ... Any Implicit Conversion Cover scala scala Int · List Suggest

scala ... (other Scala classes) ... Short · Overview scala scala · scala AnyRef Glossary scala AnyVal Byte ScalaObject «java.lang.Object» scala Null scala · · Double scala Index Contents scala Unit Nothing scala scala Float scala Boolean java.lang Figure 11.1 · Class hierarchy of Scala. Iterable String ·

T. Genet (ISTIC/IRISA) ACF-5 7/35Discuss scala T. Genet (ISTIC/IRISA)scala ACF-5 8/35 252 Long Char scala Seq ... (other Java classes) ... scala scala Int · List Suggest

scala ... (other Scala classes) ... Short ·

Glossary scala Byte scala Null · Index scala Nothing

Figure 11.1 · Class hierarchy of Scala. 252 eto 11Catr1 cl’ Hierarchy Scala’s · 11 Chapter 11.1 Section eto 11Catr1 cl’ Hierarchy Scala’s · 11 Chapter 11.1 Section

scala Subtype Any Implicit Conversion Cover scala Subtype Any Implicit Conversion Cover

Class hierarchy · Class hierarchy Overview scala scala scala · AnyRef

Overview AnyVal ScalaObject «java.lang.Object» scala scala scala AnyRef AnyVal ScalaObject «java.lang.Object» scala

· Double scala Contents scala Unit ·

Double scala Hierarchy Scala’s · 11 Chapter 11.1 Section Contents Unitscala scala Float Boolean scala Iterable java.lang scala scala String Float · Boolean scala

Discuss scala scala java.lang Iterable scala scala Long Subtype Char String · Implicit Conversion Seq

Discuss scalaAny scala Cover Long Char scala ... (other Java classes) ... scala Seq scala Int · ... (other Java classes) ... List scala Suggest scala ·

Overview Int · List scala scala ... (other Scala classes) ... Suggest scala scala AnyRef Short AnyVal ScalaObject scala «java.lang.Object» ... (other Scala classes) ...

Short ·

Glossary scala scala Byte · · Double scala scala Glossary scala Contents Unit Byte Null scala T. Genet (ISTIC/IRISA) ACF-5 9/35 T. Genet (ISTIC/IRISA) ACF-5 10 / 35 scala scala Null Float scala · Boolean Index java.lang Iterable String scala ·

· Nothing Index

Discuss scala scala Long Char scala scala Class hierarchy Seq Nothing val and var ... (other Java classes) ... val associates an object to an identifier and cannot be reassigned scala scala Figure 11.1 · Class hierarchy of Scala. Int · List var associates an object to an identifier and can be reassigned Suggest

Figure 11.1 · Class hierarchy of Scala. 252 Scala philosophy is to use val instead of var whenever possible scala ... (other Scala classes) ... Short Types are (generally) automatically252 inferred ·

Glossary scala Byte scala scala> val x=1 // or val x:Int = 1 Null x: Int = 1

· scala> x=2 Index scala :8: error: reassignment to val Nothing x=2 ˆ scala> var y=1 Figure 11.1 · Class hierarchy of Scala. y: Int = 1 252 scala> y=2 y: Int = 2

T. Genet (ISTIC/IRISA) ACF-5 11 / 35 T. Genet (ISTIC/IRISA) ACF-5 12 / 35 if expressions match - case expressions

Syntax is similar to Java if statements ... Replaces (and extends) the usual switch - case construction but that they are not statements but typed expressions The syntax is the following: e match if ( condition ) e1 else e2 { case pattern1 => r1 //patterns can be constants Remark: the type of this expression is the supertype of e1 and e2 case pattern2 => r2 //or terms with variables if ( condition ) e1 // else () ... //or terms with holes: ’ ’ Remark: the type of this expression is the supertype of e1 and Unit case => rn } Exercise 2 Remark: the type of this expression is the supertype of r1, r2, . . . rn What are the results and types of the corresponding if expressions: Example 1 (Match-case expressions) if (1==2) 1 else 2 x match { if (1==2) 1 else "toto" case "bonjour" => "hello" if (1==1) 1 case "au revoir" => "goodbye" if (1==1) println(1) case => "don’t know" }

T. Genet (ISTIC/IRISA) ACF-5 13 / 35 T. Genet (ISTIC/IRISA) ACF-5 14 / 35

(Immutable) Lists: List[A] for loops List definition (with type inference) val l= List(1,2,3,4,5) for ( ident <- s ) e Adding an element to the head of a list Remark: s has to be a subtype of Traversable val l1= 0::l (Arrays, Collections, Tables, Lists, Sets, Ranges, . . . ) Adding an element to the queue of a list Usual for-loops can be built using .to(...) val l2= l1:+6 ”(1).to(5)” ”1 to 5” results in Range(1, 2, 3, 4, 5) © Concatenating lists val l3= l1++l2 Exercise 3 Getting the element at a given position Given val lb=List(1,2,3,4,5) and using for, build the list of squares val x= l2(2) of lb. Doing pattern-matching over lists l2 match Exercise 4 { Using for and println build a usual 10 10 multiplication table. case Nil => 0 ◊ case e:: => e } T. Genet (ISTIC/IRISA) ACF-5 15 / 35 T. Genet (ISTIC/IRISA) ACF-5 16 / 35 (Immutable) Tuples : (A,B,C,...) (Immutable) maps : Map[A,B]

Map definition (with type inference) Tuple definition (with type inference) val m= Map(’C’ -> "Carbon",’H’ -> "Hydrogen") scala> val t= (1,"toto",18.3) Remark: inferred type of m is Map[Char,String] t: (Int, String, Double) = (1,toto,18.3) Finding the element associated to a key in a map, with default value Tuple getters: t. 1, t. 2, etc. m.getOrElse(’K’,"Unknown")

... or with match - case: Adding an association in a map t match case (2,"toto", ) => "found!" val m1= m+(’O’ -> "Oxygen") { case ( ,x, ) => x A Map[A,B] can be traversed (using for)asaCollection of pairs } of type Tuple[A,B], e.g. for((k,v) <- m) ... { } The above expression evaluates in "toto" Exercise 5 Print all the keys of map m1

T. Genet (ISTIC/IRISA) ACF-5 17 / 35 T. Genet (ISTIC/IRISA) ACF-5 18 / 35

Outline Basic functions

1 Basics def f ( arg1: Type1, ..., argn:Typen ): Typef = e Base types and type inference { } Control : if and match - case Remark 1: type of e (the type of the last expression of e) is Typef Loops (for) and structures: Lists, Tuples, Maps Remark 2: Typef can be inferred for non recursive functions 2 Functions Remark 3: The type of f is : (Type1,. . . ,Typen) Typef Basic functions Anonymous, Higher order functions and Partial application Example 2 3 Object Model def plus(x:Int,y:Int):Int= { Class definition and constructors println("Sum of "+x+" and "+y+" is equal to "+(x+y)) Method/operator/function definition, overriding and implicit defs x+y // no return keyword Traits and polymorphism // the result of the function is the last expression } Singleton Objects Case classes and pattern-matching Exercise 6 4 Interactions with Java Using a map, define a phone book and the functions Interoperability between Java and Scala addName(name:String,tel:String), getTel(name:String):String, 5 Isabelle/HOL export in Scala getUserList:List[String] and getTelList:List[String].

T. Genet (ISTIC/IRISA) ACF-5 19 / 35 T. Genet (ISTIC/IRISA) ACF-5 20 / 35 Anonymous functions and Higher-order functions Partial application The anonymous Scala function adding one to x is: ((x:Int) => x + 1) The ’ ’ symbol permits to partially apply a function Remark: it is written (⁄ x. x + 1) in Isabelle/HOL e.g. getTel( ) returns the function associated to getTel A higher order function takes a function as a parameter Example 3 (Other examples of partial application) e.g. method/function map called on a List[A] takes a function ( :String).size ( :Int) + ( :Int) ( :String) == "toto" (A =>B) and results in a List[B]

scala> val l=List(1,2,3) Exercise 8 l: List[Int] = List(1, 2, 3) Using map and partial application on capitalize, redefine the function capUserList. scala> l.map ((x:Int) => x+1) res1: List[Int] = List(2, 3, 4) Exercise 9 Using the higher order function filter on Lists, define a function Exercise 7 above(n:String):List(String) returning the list of users having a Using map and the capitalize method of the class String, define the capitalized name greater to name n. capUserList function returning the list of capitalized user names.

T. Genet (ISTIC/IRISA) ACF-5 21 / 35 T. Genet (ISTIC/IRISA) ACF-5 22 / 35

Outline Class definition and constructors 1 Basics Base types and type inference class C(v1: type1, . . . , vn:typen) ... Control : if and match - case { } the primary constructor Loops (for) and structures: Lists, Tuples, Maps e.g. class¸ Rational(n:Int,d:Int)˚˙ ˝ 2 { Functions val num=n // can use var instead Basic functions val den=d // to have mutable objects Anonymous, Higher order functions and Partial application def isNull:Boolean=(num==0) 3 Object Model Class definition and constructors } Method/operator/function definition, overriding and implicit defs Objects instances can be created using new: Traits and polymorphism val r1= new Rational(3,2) Singleton Objects Case classes and pattern-matching Exercise 10 4 Interactions with Java Complete the Rational class with an add(r:Rational):Rational Interoperability between Java and Scala function. 5 Isabelle/HOL export in Scala

T. Genet (ISTIC/IRISA) ACF-5 23 / 35 T. Genet (ISTIC/IRISA) ACF-5 24 / 35 Overriding, operator definitions and implicit conversions Traits Overriding is explicit: override def f(...)

Exercise 11 Traits stands for interfaces (as in Java) Redefine the toString method of the Rational class. trait IntQueue { def get:Int All operators ’+’, ’*’, ’==’, ’>’, . . . can be used as function names def put(x:Int):Unit e.g. def +(x:Int):Int= ... } Remark: when using the operator recall that x.+(y) x+y © The keyword extends defines trait implementation Exercise 12 class MyIntQueue extends IntQueue { Define the ’+’ and ’*’ operators for the class Rational. private var b= List[Int]() def get= val h=b(0); b=b.drop(1); h It is possible to define implicit (automatic) conversions between types { } def put(x:Int)= b=b:+x e.g. implicit def bool2int(b:Boolean):Int= if b 1 else 0 { } } Exercise 13 Add an implicit conversion from Int to Rational.

T. Genet (ISTIC/IRISA) ACF-5 25 / 35 T. Genet (ISTIC/IRISA) ACF-5 26 / 35

Singleton objects Type abstraction and Polymorphism Singleton objects are defined using the keyword object Parameterized function/class/trait can be defined using type parameters trait IntQueue { trait Queue[T] // more generic than IntQueue def get:Int { def get:T def put(x:Int):Unit def push(x:T):Unit } } object InfiniteQueueOfOne extends IntQueue { class MyQueue[T] extends Queue[T] def get=1 { protected var b= List[T]() def put(x:Int)= {} } def get= val h=b(0); b=b.drop(1); h { } def put(x:T)= b=b:+x A singleton object does not need to be “created” by new { } } InfiniteQueueOfOne.put(10) def first[T1,T2](pair:(T1,T2)):T1= InfiniteQueueOfOne.put(15) pair match case (x,y) => x val x=InfiniteQueueOfOne.get

T. Genet (ISTIC/IRISA) ACF-5 27 / 35 T. Genet (ISTIC/IRISA) ACF-5 28 / 35 Case classes Case classes and pattern-matching

trait Expr case class BinExpr(o:String,l:Expr,r:Expr) extends Expr Case classes provide a natural way to encode Algebraic Data Types case class Constant(r:Rational) extends Expr e.g. binary expressions built over rationals: 18 + ( 1 ) case class Inv(e:Expr) extends Expr 27 ≠ 2 trait Expr case class BinExpr(o:String,l:Expr,r:Expr) extends Expr match case can directly inspect objects built with case classes case class Constant(r:Rational) extends Expr def getOperator(e:Expr):String= { case class Inv(e:Expr) extends Expr e match { case BinExpr(o,_,_) => o Instances of case classes are built without new case _ => "No operator" e.g. the object corresponding to 18 + ( 1 ) is built using: 27 ≠ 2 BinExpr("+",Constant(new Rational(18,27)), } Inv(Constant(new Rational(1,2)))) } Exercise 14 Define an eval(e:Expr):Rational function computing the value of any expression.

T. Genet (ISTIC/IRISA) ACF-5 29 / 35 T. Genet (ISTIC/IRISA) ACF-5 30 / 35

Outline Interoperablity between Java and Scala 1 Basics In Scala, it is possible to build objects from Java classes Base types and type inference Control : if and match - case e.g. val txt:JTextArea=new JTextArea("") Loops (for) and structures: Lists, Tuples, Maps And to define scala classes/objects implementing Java interfaces 2 Functions e.g. object Window extends JFrame Basic functions Anonymous, Higher order functions and Partial application There exists conversions between Java and Scala data structures 3 Object Model import scala.collection.JavaConverters._ Class definition and constructors Method/operator/function definition, overriding and implicit defs val l1:java.util.List[Int]= new java.util.ArrayList[Int]() Traits and polymorphism l1.add(1); l1.add(2); l1.add(3) // l1: java.util.List[Int] Singleton Objects Case classes and pattern-matching val sb1= l1.asScala.toList // sl1: List[Int] val sl1= sb1.asJava // sl1: java.util.List[Int] 4 Interactions with Java Interoperability between Java and Scala } 5 Isabelle/HOL export in Scala Remark: it is also possible to use Scala classes and Object into Java

T. Genet (ISTIC/IRISA) ACF-5 31 / 35 T. Genet (ISTIC/IRISA) ACF-5 32 / 35 Outline Isabelle/HOL exports Scala case classes and functions... 1 Basics theory tp Base types and type inference [...] Control : if and match - case datatype ’a tree= Leaf | Node "’a * ’a tree * ’a tree" fun member:: "’a ’a tree bool" Loops (for) and structures: Lists, Tuples, Maps ∆ ∆ where 2 Functions "member _ Leaf = False" | Basic functions "member x (Node(y,l,r)) = (if x=y then True else ((member x l) Anonymous, Higher order functions and Partial application (member x r)))" ‚ 3 Object Model to Scala Class definition and constructors object tp Method/operator/function definition, overriding and implicit defs { Traits and polymorphism abstract sealed class tree[+A] // similar to traits Singleton Objects case object Leaf extends tree[Nothing] Case classes and pattern-matching case class Node[A](a: (A, (tree[A], tree[A]))) extends tree[A] def member[A : HOL.equal](uu: A, x1: tree[A]): Boolean = 4 Interactions with Java (uu, x1) match { Interoperability between Java and Scala case (uu, Leaf) => false 5 Isabelle/HOL export in Scala case (x, Node((y, (l, r)))) => (if (HOL.eq[A](x, y)) true else member[A](x, l) || member[A](x, r))

T. Genet (ISTIC/IRISA) ACF-5 33 / 35 T. Genet} (ISTIC/IRISA) ACF-5 34 / 35 }

... and some more cryptic code for Isabelle/HOL equality object HOL { trait equal[A] { val ‘HOL.equal‘: (A, A) => Boolean } def equal[A](a: A, b: A)(implicit A: equal[A]): Boolean = A.‘HOL.equal‘(a, b)

def eq[A : equal](a: A, b: A): Boolean = equal[A](a, b)

} To link Isabelle/HOL code and Scala code, it can be necessary to add: (Demo tp.thy + CM5Integ) implicit def equal_t[T]: HOL.equal[T] = new HOL.equal[T] { val ‘HOL.equal‘ = (a: T, b: T) => a==b } Which defines HOL.equal[T] for all types T as the Scala equality == T. Genet (ISTIC/IRISA) ACF-5 35 / 35