Scala en

2,778
-1

Published on

Published in: Technology, News & Politics
0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
2,778
On Slideshare
0
From Embeds
0
Number of Embeds
25
Actions
Shares
0
Downloads
17
Comments
0
Likes
1
Embeds 0
No embeds

No notes for slide

Scala en

  1. 1. Scala<br />František Kocun<br />
  2. 2. “I can honestly say if someone had shown me the Programming in Scala book by Martin Odersky, Lex Spoon & Bill Venners back in 2003 I'd probably have never created Groovy.“<br />JamesStrachan, Groovy creator<br />
  3. 3. “No other language on the JVM seems as capable of being a "replacement for Java" as Scala, and the momentum behind Scala is now unquestionable.“<br />CharlesNutter, JRubycoredeveloper<br />
  4. 4. “Scala.“<br />JamesGosling, Java creator<br />Answer on a question, which language would he use now on JVM except Java.<br />
  5. 5. “On my radar, the current best exit strategy for Java is Scala.„<br />BruceEckel,author of many books<br />
  6. 6. Scala vs Java<br />Scala removes<br />break, continue, goto<br />static<br />primitive types<br />raw types (every type parameter „generics“ has to be stated)<br />operators (all are methods)<br />override is not more optional<br /> (when overriding in Scala one has to declare override)<br />
  7. 7. Scala vs Ruby and Groovy<br />Scala has two type of fans<br />Java programmers (pros of functional programming)<br />Ruby programmers (pros of language with static typing)<br />Implicits, structural typing and type inference, resembles work with language with dynamic typing<br />Scala is compiles a compiled language and all types are checked in compilation time<br />one can not call a non existing method<br />no ClassCastException in runtime<br />possibility to refactor<br />as fast as Java <br />
  8. 8. Scala unifies FP and OOP<br />
  9. 9. Why to unify FP and OOP<br />Both approaches are complementary<br />Functional<br />Object-oriented<br />Abstraction<br />Functions<br />Higher-order functions<br />Parametric <br /> polymorphism<br />Extending, state dependent behavior<br />Inheritance<br />Polymorphism<br />Encapsulation<br />Dynamic configuration<br />
  10. 10. Where?<br />Manipulation of data structures <br />collections, trees, ADTs, ...<br />Internal/External DSLs<br />OSGi, Apache Camel, scala-query, <br /> specs, built-in parser<br />Modular applications<br />Mixins, dependency injection, DCI (data, context & interaction)<br />
  11. 11. How?<br /><ul><li>Function as input argument
  12. 12. Pattern matching, case classes
  13. 13. Parametric polymorphism
  14. 14. Traits
  15. 15. Higher-order functions
  16. 16. Function as output argument
  17. 17. Implicits</li></ul>Manipulation of data structures <br />collections, trees, ADTs, ...<br />Internal/External DSLs<br />OSGi, Apache Camel, scala-query, <br /> specs, built-in parser<br />Modular applications<br />Mixins, dependency injection, DCI (data, context & interaction)<br />
  18. 18. Function as value<br />Manipulation of data structures<br />Collections<br />Trees<br />DSL<br />
  19. 19. Example - filtering<br />Java<br />public Collection<Ticket> approved(Collection<Ticket> tickets){<br /> Collection<Ticket> result = new ArrayList<Ticket>();<br />for(Ticket ticket : tickets){<br />if(ticket.getState() == State.APPROVED)<br />result.add(icket);<br /> }<br />return result;<br />}<br />
  20. 20. Example - filtering<br />Java<br />publicCollection<Ticket> approved(Collection<Ticket> tickets){<br />Collection<Ticket> result = new ArrayList<Ticket>();<br />for(Ticketticket: tickets){ filter<br />if(ticket.getState()== State.APPROVED)<br />result.add(ticket);<br />}<br />returnresult;<br />}<br />With what?<br />What to do?<br />How?<br />
  21. 21. Yes, it can be done in Java<br />Interface for conditon<br />... and the use<br />Filter util method<br />publicinterfaceICondition<T> {<br />publicbooleancheck(T toBeChecked);<br />}<br />publicstatic <T> Collection<T> filter(Collection<T> ts, ICondition<T> c){<br />Collection<T> result = new ArrayList<T>();<br />for(T t : ts)<br />if(c.check(t)) result.add(t);<br />returnresult;<br />}<br />CollestionUtils.filter(verzie, new ICondition<Ticket>() {<br /> public boolean check(TickettoBeChecked)<br /> {<br /> return toBeChecked.getState() == State.APPROVED;<br /> }<br />});<br />
  22. 22. Example - filtering<br />Scala<br />defapproved(tickets: List[Ticket]) {<br /> tickets filter (_.getState() == State.APPROVED) <br />}<br />
  23. 23. WTF ?<br />What type has the parameter in the function „filter“?<br />List[+A]{<br />deffilter (p : (A) => Boolean) : List[A] <br />}<br />Java : (A) => Boolean<br />public interface Function1<O, I> {<br /> O apply(I input);<br />}<br />interface ICondition<I> extends IFunction1<Boolean, I> {}<br />
  24. 24. Scala List<br />count (p : (A) => Boolean) :Int<br />exists (p : (A) => Boolean) : Boolean<br />filter (p : (A) => Boolean) : List[A] <br />find (p : (A) => Boolean) : Option[A] <br />foldLeft [B](z : B)(f : (B, A) => B) : B<br />forall (p : (A) => Boolean) : Boolean<br />foreach (f : (A) => Unit) : Unit<br />map [B](f : (A) => B) : List[B] <br />remove (p : (A) => Boolean) : List[A] <br />
  25. 25. Scala List<br />Most of them is inherited from trait Iterable. So every collection, array has them, because they inherit from Iterable.<br />Similar functions can be written for trees.<br />count (p : (A) => Boolean) :Int<br />exists (p : (A) => Boolean) : Boolean<br />filter (p : (A) => Boolean) : List[A] <br />find (p : (A) => Boolean) : Option[A] <br />foldLeft [B](z : B)(f : (B, A) => B) : B<br />forall (p : (A) => Boolean) : Boolean<br />foreach (f : (A) => Unit) : Unit<br />map [B](f : (A) => B) : List[B] <br />remove (p : (A) => Boolean) : List[A] <br />
  26. 26. Function can be assigned to variable<br />varf : (String => Unit) = (x) => println(x)<br />Function can be passed to another function<br />tickets filter (t => t.getState() == State.APPROVED)<br />Return value from function can be a function <br />defdeductKind = tax | insurance | retirement<br />Function is primitive type, basic building block, with the same importance as an integer or a string.<br />If functions takes another function as an argument or if it returns a function, it is called a higher-order function.<br />
  27. 27. Examples<br />Numbers multiplied by two<br />Employees to DTOs<br />List(1, 2, 3, 4, 5) map { _ * 2 }<br />> List[Int] = List(2, 4, 6, 8, 10)<br />caseclassEmployee( varname : String)<br />caseclass DTOEmployee( var name : String)<br />deftoDto(e : Employee) = newDTOZamestnanec(z.meno)<br />List(newEmployee(“John"), newEmployee(“Jack")) <br />maptoDto<br />> List[DTOEmployee] = List(DTOEmployee(John), DTOEmployee(Jack))<br />
  28. 28. Type declaration<br />In Scala types are written after colon<br />exists (p : (A) => Boolean) : Boolean<br />var age :Int= 24 val age = 33<br />If type is unambiguous, it doesn’t have to be declared<br />Return type of function exists<br />Argument p is of type function from A to Boolean<br />Type of variableage<br />
  29. 29. ValvsVar<br /><ul><li> immutable</li></ul> (v Java it would be final)<br /><ul><li> creates field and getter</li></ul>valage:Int=22<br />age = 33 //ERROR<br /><ul><li> variable
  30. 30. creates field, getter </li></ul> and setter<br />varage:Int=22<br />age = 33<br />
  31. 31. List<br />Operator :: is bound from right<br />val list1 = List("Programming", "Scala") <br />val list2 = "People" :: "should" :: "read" :: list1<br />val list2 = ("People" :: ("should" :: ("read" :: list1))) <br />val list2 = list1.::("read").::("should").::("People")<br />list2<br />
  32. 32. Map<br />State -> Capital<br />is mapped to<br />State -> length of the capital name<br />valstateCapitals = Map(<br />"Alabama" -> "Montgomery",<br /> "Alaska" -> "Juneau",<br /> "Wyoming" -> "Cheyenne")<br />vallengths = stateCapitalsmap { kv => (kv._1, kv._2.length)} <br />println(lengths)<br />> Map(Alabama -> 10, Alaska -> 6, Wyoming -> 8)<br />
  33. 33. FoldLeft<br />deffoldLeft[B](z: B)(op: (B, A) => B): B = <br />thismatch{<br />caseNil => z<br />case x :: xs => (xsfoldLeftop(z, x))(op)<br />}<br />
  34. 34. FoldLeft<br />List(1,2,3,4,5).foldLeft(10)(_ * _)<br />(((((10 * 1) * 2) * 3) * 4) * 5)<br />List(1,2,3,4,5).foldLeft(10)( (x, y) => x +y)<br />(((((10 + 1) + 2) + 3) + 4) + 5)<br />Shortcut for arguments of anonymous functions. First underscore means the first argument, second the second…<br />
  35. 35. Questions<br />How would we write function “sum” with the help of foldLeft?<br />defdistinct[A](l : List[A]) : List[A] = <br /> (l foldLeft List[A]()) <br /> {(res, a)=> if (!res.contains(a)) a :: reselseres}<br />defsumInt(l : List[Int]) : Int = l.foldLeft(0)(_ + _)<br />How would we write function “distinct“with the help of foldLeft? (Selects only distinct elements form the list.)<br />
  36. 36. Every value is an objectEvery operator a method<br />factorial(x - 1)<br />factorial (x.-(1))<br />map.containsKey(‘a’)<br />map containsKey ‘a’<br />There are no operators in Scala. Method names can contain some symbols.<br />Every method can be called on the object without the dot and the brackets.<br />
  37. 37. There are no operators in Scala. <br />Method names can contain some symbols.<br />trait Ordered[A] extendsjava.lang.Comparable[A] {<br />def compare(that: A): Int<br />def < (that: A): Boolean = (this compare that) < 0<br />def > (that: A): Boolean = (this compare that) > 0<br />def <= (that: A): Boolean = (this compare that) <= 0<br />def >= (that: A): Boolean = (this compare that) >= 0<br />defcompareTo(that: A): Int = compare(that)<br />}<br />
  38. 38. “While” doesn’t have to be a keyword... But it is...<br />defwhileAwesome(conditional: => Boolean)(f: => Unit) {<br />if (conditional) {<br /> f<br />whileAwesome(conditional)(f)<br /> }<br />}<br />var count = 0<br />whileAwesome(count < 5) {<br />println("still awesome")<br /> count += 1<br />}<br />>stillawesome<br />stillawesome<br />stillawesome<br />stillawesome<br />stillawesome<br />Conditionalis of type (=> Boolean) , so it is evaluated in the function “whileAwesome”<br />If conditionalwas of typeBoolean, it would be evaluated before calling the function so the loop would never stop writing"still awesome"<br />
  39. 39. It has many real life uses<br />tx{ <br />valperson = new Person(id=null, name= "Ivanka"); <br />manager.persist(person) <br />}<br />deftx(f: => Unit) = {<br />manager.getTransaction().begin()<br />try {<br />tx<br />manager.getTransaction().commit()<br /> } catch {<br />casee: Exception => manager.getTransaction().rollback()<br /> }<br />}<br />
  40. 40. Functions are objects too<br />traitFunction1[-S, +T] {<br />defapply(x: S):T<br />}<br />E.g. anonymous function (x: Int ) => x + 1 is translated by the compiler to<br />new Function1[Int, Int] {<br /> def apply(x: Int): Int = x + 1<br />}<br />
  41. 41. Functions are objects too<br />While (=>)is a class, it can be inherited from it.<br />So we can specialize the concept of a function.<br />Instead of<br />a(i) = a(i) + 2<br />we can write<br />a.update(i, a.apply(i) + 2)<br />Array[T] is a function Int => T, so if such function is needed we can pass an Array[T]<br />classArray[T] ( length: Int) extends(Int=> T) {<br />deflength: Int= ...<br />defapply(i: Int): T= ...<br />defupdate(i: Int, x: T): Unit= ...<br />defelements: Iterator[T] = ...<br />defexists(p: T => Boolean):Boolean<br /> = ...<br />}<br />
  42. 42. Currying<br />Partial function application<br />
  43. 43. Currying<br />Function can return a function<br />def cat(s1: String)(s2: String) = s1 + s2<br />def cat(s1: String) = (s2: String) => s1 + s2<br />cat("foo")("bar") <br />> java.lang.String = foobar<br />cat("foo") returns a function {(s2 : Int) => “foo” + s2}, to which is passed an argument "bar" <br />Both notations are correct<br />
  44. 44. Currying<br />def cat(s1: String, s2: String) = s1 + s2<br />> cat: (String,String) java.lang.String<br />valcurryCat = Function.curried(cat _)<br />> curryCat: (String) => (String) => java.lang.String= <function><br />cat("foo", "bar") == curryCat("foo")("bar")<br />> res2: Boolean = true<br />Function.curried() converts functions to their curried form<br />
  45. 45. Partial function application<br />val curryCat = Function.curried(cat _)<br />> curryCat: (String) => (String) => java.lang.String= <function><br />val partialCurryCat = curryCat("foo")(_)<br />> partialCurryCat: (String) => java.lang.String = <function><br />partialCurryCat("bar")<br />> res3: java.lang.String = foobar<br />Partial application= we didn’t passed all parameters<br />
  46. 46. Partial function application<br />It is not needed to pass all parameters<br />Uses Currying<br />val numbers= List(1, 2, 3, 4, 5);<br />println( numbers map ( 8 +))<br />def plus(a : Int)(b : Int) : Int = a + b<br />val plusFive = plus(5) _<br />println( numbers map plusFive )<br />f(A : a)(B : b) : C<br />f(B : b) : C<br />
  47. 47. „There are two ways of constructing a software design.  One way is to make it so simple that there are obviously no deficiencies. And the other way is to make it so complicated that there are no obvious deficiencies.”<br />C.A.R. Hoare, author of Quicksort<br />
  48. 48. Quicksort<br />def sort(xs: Array[Int]) {<br />defswap(i: Int, j: Int) {<br />val t = xs(i); xs(i) = xs(j); xs(j) = t<br />}<br />def sort1(l: Int, r: Int) {<br />val pivot = xs((l + r) / 2)<br />var i = l; var j = r<br />while (i <= j) {<br />while (xs(i) < pivot) i += 1<br />while (xs(j) > pivot) j -= 1<br />if (i <= j) {<br />swap(i, j)<br />i += 1<br />j -= 1<br />}<br />}<br />if (l < j) sort1(l, j)<br />if (j < r) sort1(i, r)<br />}<br />sort1(0, xs.length 1)<br />}<br />Functional<br />Imperative<br />def sort(xs: Array[Int]): Array[Int] =<br />if (xs.length <= 1) xs<br />else {<br />val pivot = xs(xs.length / 2)<br />Array.concat(<br /> sort(xs filter (pivot >)),<br />xs filter (pivot ==),<br /> sort(xs filter (pivot <)))<br />}<br />
  49. 49. Implicits<br />Implicit conversions<br />
  50. 50. Implicits<br />Only single implicit can be used (they can not chain)!<br />println(intToPimpedInt(3).minutes())<br />implicitdefintToPimpedInt(i : Int) = newPimpedInt(i)<br />defmain(args: Array[String]) {<br /> 3 timesprintln("sdfs")<br />println(5 minutes)<br />}<br />classPimpedInt(i : Int){<br />deftimes(f : => Unit) : Unit = for(x <- 0 until i) f<br />defseconds = 1000 * i<br />defminutes = 60 * seconds<br />}<br />intToPimpedInt(3).times(println("sdfs"))<br />times(f : => Unit)<br />seconds()<br />minutes()<br />
  51. 51. objectComplex {<br />val i = newComplex(0, 1)<br />implicitdef double2complex(x: Double) : Complex = newComplex(x, 0)<br />}<br />classComplex(valre: Double, val im: Double) {<br />def + (that: Complex): Complex = new Complex(this.re + that.re, this.im + that.im)<br />def - (that: Complex): Complex = new Complex(this.re - that.re, this.im - that.im)<br />def * (that: Complex): Complex = new Complex(this.re * that.re - this.im * that.im,<br />this.re * that.im + this.im * that.re)<br />def / (that: Complex): Complex = { <br />valdenom = that.re * that.re + that.im * that.im<br />new Complex((this.re * that.re + this.im * that.im) / denom,<br /> (this.im * that.re - this.re * that.im) / denom)<br />}<br />overridedeftoString = re+(if (im < 0) "-"+(-im) else"+"+im)+"*i"<br />}<br />By importing Complex one can use complex numbers like they were built in language feature.<br />import pads.Complex._<br />objectComplexTest {<br />defmain(args: Array[String]) {<br /> val x : Complex = 4 + 3 * i<br />val y : Complex = x * i <br />println(y)<br />}<br />}<br />
  52. 52. Structural typing<br />“Type safe duck typing”<br />
  53. 53. Structuraltyping<br />classEmployee {<br />varmeno : String = null<br />}<br />classFirm {<br />var title : String = null<br />def name = "Firm is called " + title<br />}<br />Attribute name<br />Method name<br />Employee and Firm does not have a common supertype<br />
  54. 54. Structural typing<br />defgetName(x : {val name : String}) : String = x.name<br />defsetName(x : {var name : String}) : Unit = x.name = "new name"<br />val employee = new Employee()<br />employee.name = “Kate"<br />val firm = new Firm()<br />firm.name = "PosAm"<br />println (getName(employee))<br />println (getName(firm))<br />println (setName(employee))<br />println (setName(firm)) //ERROR<br />type mismatch; found : firm.type (with underlying type pads.Firm) required: AnyRef{def name: String; defname_=(x$1: String): Unit}<br />
  55. 55. DSL - domain specific language<br />ImplicitsHigher order functionsOptional dots, semi-colons, parenthesesOperators like methodsCurrying<br />
  56. 56. DSL<br />External DSL<br /> + own language, freedom<br /> - need to write a parser<br /> - extensible from inside<br />Internal DSL<br /> + extensible from outside, <br /> it’s just a library<br /> - syntax of a host language<br />Parser library in Scala simplifies writing external DSLs<br />Implicits, higher-order functions, optional dots and brackets, operator methods and currying simplifies writing of internal DSLs<br />
  57. 57. External DSL written with the help of library scala.util.parsing.combinator._<br /> /** @returnParser[Money] */<br />defpercentage = toBe ~> doubleNumber <~ "percent" <~ "of" <~ "gross" ^^ {<br />percentage => grossAmount * (percentage / 100.)<br /> }<br />defamount = toBe ~> doubleNumber <~ "in" <~ "gross" <~ "currency" ^^ {<br /> Money(_)<br /> }<br />deftoBe = "is" | "are"<br />defdoubleNumber = floatingPointNumber ^^ { _.toDouble }<br />|, ~> , <~, ^^ are just functions<br />Library pasing.combinator is internal DSL<br />
  58. 58. ^^<br /> /** A parser combinator for function application <br /> *<br /> *<p>`p ^^ f' succeeds if `p' succeeds; it returns `f' applied to the result of `p'.</p><br /> *<br /> * @param f a function that will be applied to this parser's result (see `map' in `ParseResult').<br /> * @return a parser that has the same behaviour as the current parser, but whose result is<br /> * transformed by `f'.<br /> */<br />def ^^ [U](f: T => U): Parser[U] = map(f).named(toString+"^^")<br />
  59. 59. Trait<br />Mixins<br />Dependency injection <br />Data, context & interaction<br />
  60. 60. Types<br />Object has only a single instance. One can obtain this instance by writing object’s name. It can be extended by the Traits.<br />Class can inherit from one class but it can be extended by several Traits.<br />Like an interface/abstract class.<br />Can have an implementation.<br />Can not have a constructor.<br />Class<br />Object<br />Trait<br />
  61. 61. Dependency injection<br />classUserRepository{<br />def authenticate(user: User): User = { <br />println("authenticating user: " + user) <br /> user <br /> } <br />def create(user: User) = println("creating user: " + user) <br />def delete(user: User) = println("deleting user: " + user) <br />} <br />classUserService { <br />def authenticate(username: String, password: String): User = <br />userRepository.authenticate(username, password) <br />def create(username: String, password: String) = <br />userRepository.create(new User(username, password)) <br />def delete(user: User) = All is statically typed. <br />userRepository.delete(user) <br />} <br />UserService is dependent on<br />UserRepository. It can have more implementations as well.<br />UserRepository can have more implementations.<br />
  62. 62. Cake Pattern<br />traitUserRepositoryComponent{<br />valuserRepository: UserRepository<br />classUserRepository { <br /> ... <br /> } <br />} <br />traitUserServiceComponent { <br />this: UserRepositoryComponent => <br />valuserService: UserService<br />classUserService {<br /> ... <br /> }<br />}<br />Classes are wrapped in components (traits), where its dependencies are declared.<br />
  63. 63. Cake Pattern<br />objectComponentRegistryextends <br />UserServiceComponentwith <br />UserRepositoryComponent<br />{<br />valuserRepository = newUserRepository<br />valuserService = newUserService<br />}<br />In the result object we set implementations of all necessary components. Every component uses right implementation on which it is dependent.<br />
  64. 64. Case class<br />ADT<br />Pattern matching<br />
  65. 65. Pattern matching<br />Matching by values<br />Java swicht-case analogy<br />valrandomInt = new Random().nextInt(10)<br />randomIntmatch {<br />case 7 => println( "lucky seven!" )<br />caseotherNumber => println(„not seven "+ otherNumber)<br />}<br />
  66. 66. Pattern matching<br />Matching by type<br />val sundries = List(23, "Hello", 8.5, 'q')<br />for (sundry <- sundries) { <br /> sundry match { <br />casei: Int => println("got an Integer: " + i) <br />case s: String => println("got a String: " + s) <br />case f: Double => println("got a Double: " + f) <br />case other => println("got something else: " + other) <br /> } <br />}<br />
  67. 67. Pattern matching<br />Matching of sequences<br />valwillWork = List(1, 3, 23, 90)<br />valwillNotWork = List(4, 18, 52)<br />val empty = List()<br />for (l <- List(willWork, willNotWork, empty)) {<br /> l match {<br />case List(_, 3, _, _) => println("4 elements, with the 2nd being '3'.")<br />case List(_*) => println("Any other list with 0 or more elements.")<br /> }<br />}<br />
  68. 68. Pattern matching<br />Matching of tuples<br />valtupA = ("Good", "Morning!") <br />valtupB = ("Guten", "Tag!") <br />for(tup <- List(tupA, tupB)) { <br />tupmatch { <br />case(thingOne, thingTwo) ifthingOne == "Good" <br /> => println("A two-tuple starting with 'Good'.")<br />case(thingOne, thingTwo) <br /> => println("Two things: " + thingOne + " and " + thingTwo) <br /> } <br />}<br />
  69. 69. Pattern matching<br />Matching of case classes<br />caseclass Person(name: String, age: Int)<br />valalice = new Person("Alice", 25)<br />val bob = new Person("Bob", 32)<br />valcharlie = new Person("Charlie", 32)<br />for (person <- List(alice, bob, charlie)) {<br /> person match {<br />case Person("Alice",25) => println("Hi Alice!")<br />case Person("Bob", 32) => println("Hi Bob!")<br />case Person(name, age) <br /> => println(age + " years old person named " + name )<br /> }<br />}<br />
  70. 70. Recap<br />Scala is a multi-paradigm language<br />Object-oriented – objects, classes, traits, inheritance, polymorphism, encapsulation<br />Functional – function is a value, pattern matching, parametric polymorphism (generics), case classes<br />(Dynamic-types) – implicits, traits, structural typing, type inference <br /> These features give programmers a feel of language with dynamic types. Although all types are checked in compilation time.<br />
  71. 71. And I haven’t mention<br />Implicit function parameters<br />Lazy values<br />XML built in syntax<br />Actor<br /> ...<br />And it works with Hibernate, Spring, Guice, Maven, Wicket...<br />
  72. 72. Want to know more?<br />programming-scala.labs.oreilly.com<br />www.scala-lang.org<br />
  73. 73. Finally end<br />
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×