Scala overview

88
민형기 S-Core Cloud Computing Lab Data Solution Part 2013. 2. 18.

description

 

Transcript of Scala overview

Page 1: Scala overview

민형기

S-Core Cloud Computing Lab

Data Solution Part

2013. 2. 18.

Page 2: Scala overview

1

Contents

I. Scala란?

II. Scala는 간결하다.

III. Scala는 객체지향 언어이다.

IV. Scala는 함수형 언어이다.

V. Scala는 동적 언어이다.

VI. Scala는 정적으로 타입화된 언어이다.

VII. Scala는 많은 좋은 기능이 있다.

VIII.Scala를 어떻게 공부하지?

Page 3: Scala overview

2

Scala 란?

object Hello {

def main(args:Array[String]) {

println(“Hello, World”)

}

}

Page 4: Scala overview

3

Scala 정의

Scala [skah-lah] = scalable language

The language is so named because it was designed to grow with the demands of its users.

-Programming In Scala, p39

The language is so named because it was designed to grow with the demands of its users.

-Programming In Scala, p39

Scala is a modern multi-paradigm programming language designed to express common programming patterns in a concise, elegant, and type-safe way.

-scala-lang.com

Scala is a modern multi-paradigm programming language designed to express common programming patterns in a concise, elegant, and type-safe way.

-scala-lang.com

Page 5: Scala overview

4

Scala에 대한 의견들

If I were to pick a language to use on the JVM today other than Java, it would be Scala.

-James Gosling, creater of Java

If I were to pick a language to use on the JVM today other than Java, it would be Scala.

-James Gosling, creater of Java

Scala, it must be stated, is the current heir apparent to the Java throne. No other language on the JVM seems as capable of being a “replacement for Java” as Scala, and the momentum behind Scala is now uniquestionable.

- Charlies Nutter, JRuby lead

Scala, it must be stated, is the current heir apparent to the Java throne. No other language on the JVM seems as capable of being a “replacement for Java” as Scala, and the momentum behind Scala is now uniquestionable.

- Charlies Nutter, JRuby lead

My tip thought for the long term replacement of javac is Scala. I’m very impressed with it! I can honestly say if someone had shown me the Programming in Scala book […] back in 2003. I’d probably have never created Groovy.

-James Strachan, creator of Groovy

My tip thought for the long term replacement of javac is Scala. I’m very impressed with it! I can honestly say if someone had shown me the Programming in Scala book […] back in 2003. I’d probably have never created Groovy.

-James Strachan, creator of Groovy

http://www.adam-bien.com/roller/abien/entry/java_net_javaone_which_programming

http://macstrac.blogspot.com/2009/04/scala-as-long-term-replacement-for.html

http://blog.headius.com/2009/04/future-part-one.html

Page 6: Scala overview

5

Scalability in Programming Language

어플리케이션이 사용자의 요구에 맞추기 위해 크기나 용량을 변경해도, 그 기능이 계속하여 잘 동작 할 수 있는 능력

-Terms

어플리케이션이 사용자의 요구에 맞추기 위해 크기나 용량을 변경해도, 그 기능이 계속하여 잘 동작 할 수 있는 능력

-Terms

문제 영역의 크기나 복잡도가 증가하여도 유사한 방법으로 문제 해결이 가능한 것. - 빌딩 블록의 수가 증가하면 추상화 / 축약 - 언어의 지원 / 라이브러리 / 프레임 워크

문제 영역의 크기나 복잡도가 증가하여도 유사한 방법으로 문제 해결이 가능한 것. - 빌딩 블록의 수가 증가하면 추상화 / 축약 - 언어의 지원 / 라이브러리 / 프레임 워크

Page 7: Scala overview

6

언어 확장의 예시 – 분수 (Rational)

규칙: (a, b) 단, b != 0 (a, b) + (c, d) = (ad+bc, bd) (a, b) * (c, d) = (ac, bd)

규칙: (a, b) 단, b != 0 (a, b) + (c, d) = (ad+bc, bd) (a, b) * (c, d) = (ac, bd)

*기타 - Big Integer - Complex number - Vector - Matrix …

*기타 - Big Integer - Complex number - Vector - Matrix …

Page 8: Scala overview

7

BigInteger vs. BigInt

public BigInteger factorial(BigInteger x) {

if ( x == BigInteger.ZERO )

return BigInteger.ONE;

else

return x.multiply(

factorial (x.subtract(BigInteger.ONE)));

}

def factorial(x: BigInt):BigInt =

if (x == 0) 1 else x * factorial(x-1)

Java

Scala

Integer와

유사하지 않음

출처: http://www.artima.com/scalazine/articles/scalable-language.html

Page 9: Scala overview

8

Google Trends

출처: http://www.google.com/trends/explore#q=scala,%20clojure,%20groovy

Page 10: Scala overview

9

Job Trends

출처: http://www.indeed.com/jobtrends?q=scala%2C+clojure%2C+groovy&l=

Page 11: Scala overview

10

Scala Today

출처: http://www.slideshare.net/Odersky/devoxx

Page 12: Scala overview

11

Scala Best Practices

출처: http://www.slideshare.net/mslinn/scala-adoption-by-enterprises

Twitter –Kestrel: queuing

–FlockDB(and Gizzard): social graph store

–Hawkwind: people search

–Hosebird: streaming API

–Scalding: MapReduce Wrapper (build on top of Cascading)

Guardian: Open Platform –2009.11: java + guice + guice servlets + apache solr

–2010.01: Integration tests with ScalaTest / maven scala plugin

–2010.03: scala + guice + guice servlets + apache solr

–2010.06: maven -> sbt

–2011.06: scala + lift + apache solr ( 5k loc -> 3.5k)

in Java 1.5: Pair p = new Pair<Integer, String>(1, "Scala");

in Scala: val p = new MyPair(1, "scala");

Page 13: Scala overview

12

Scala 언어 가계도

Scala

Java

C

C++

Simula

Smalltalk

Prolog

Erlang Haskell

ML

Lisp

functional

programming syntax

objects

pattern

matching

Actors

Page 14: Scala overview

13

Scala를 멀리서 보기

함수형

프로그래밍

객체 지향

프로그래밍

동적

프로그래밍

강화된 타입 시스템

JVM/.Net

※동적 프로그래밍: 스칼라는 엄밀히 말하자면 동적 언어는 아니지만, 동적 언어에서 제공하는 많은 특징을 가지고 있다.

(간결함(Concise), REPL, 고수준함수, Duck Typing 등)

Page 15: Scala overview

14

Scala 특징 1/3

Scala는 함수형과 객체지향형의 성격을 다 가지고 있다. –Method를 포함한 모든 함수 (function)은 값(value)이다.

–모든 값(value)는 객체(object)이다.

Scala는 정적 타입시스템이다. –강력한 타입 추론 시스템: in Java 1.5: Pair p = new Pair<Integer, String>(1, "Scala");

in Scala: val p = new MyPair(1, "scala");

Page 16: Scala overview

15

Scala 특징 2/3

가벼운 문법(lightweight syntax)

–Anonymous functions

–Higher-order functions

–Nested Functions

–Currying

ML-style의 Pattern Matching

XML과 통합

–Scala 프로그램에서 XML을 직접 쓸 수 있다.

–Scala 클래스 정의로 XML DTD로 변환할 수 있다.

정규식 패턴

DSLs

Concurrency via actors

Page 17: Scala overview

16

Scala 특징 3/3 – Scala는 실용적이다.

Java를 대체해서 사용이 가능함

Java와 Scala를 혼합한 프로젝트가 가능

기존 Java 라이브러리를 활용가능

기존 Java 툴(Ant, Maven, Junit, etc…)을 활용가능

기존 IDE 환경을 지원 (Eclipse, NetBeans, IntelliJ)

Page 18: Scala overview

17

Scala compared to Java

Scala adds Scala removes

+ a pure object system - static members

+ operator overloading - primitive Types

+ closures - break, continue

+ mixin composition with traits - special treatment of interfaces

+ existential types - wildcards

+ abstract types - raw types

+ pattern matching - enums

Modeled in libiaries:

assert, enums, properties, events, actors, using, queries, …

출처: http://www.slideshare.net/Odersky/fosdem-2009-1013261

Page 19: Scala overview

18

Scala는 간결하다.

object Hello {

def main(args:Array[String]) {

println(“Hello, World”)

}

}

Page 20: Scala overview

19

Type Interface

val sum = 1 + 2 + 3 >sum: Int = 6 val nums = List(1, 2, 3) >nums: List[Int] = List(1, 2, 3) val map = Map("abc" -> List(1,2,3)) >map: scala.collection.immutable.Map[java.lang.String,List[Int]] = Map(abc -> List(1, 2, 3))

Page 21: Scala overview

20

Explicit Types

val sum: Int = 1 + 2 + 3 val nums: List[Int] = List(1, 2, 3) val map: Map[String, List[Int]] = ...

Page 22: Scala overview

21

Higher Level

// Java – Check if string has uppercase character

boolean hasUpperCase = false;

for(int i = 0; i < name.length(); i++) {

if(Character.isUpperCase(name.charAt(i))) {

hasUpperCase = true;

break;

}

}

// Scala

val hasUpperCase = name.exists(_.isUpperCase)

Page 23: Scala overview

22

Less Boilerplate

public class Person {

private String name;

private int age;

public Person(String name, int age) {

this.name = name;

this.age = age;

}

public String getName() {

return name;

}

public int getAge() {

return age;

}

public void setName(String name) {

this.name = name;

}

public void setAge(int age) {

this.age = age;

}

}

class Person(var name: String,

var age: Int)

Java

class Person(var name: String,

private var _age: Int){

def age = _age // Getter

def age_=(newAge:Int) { // Setter

_age = newAge

}

}

Scala

Page 24: Scala overview

23

Variables and Values

// variable

var foo = "foo"

foo = "bar" // okay

// value

val bar = "bar"

bar = "foo" // nope

Page 25: Scala overview

24

Scala는 객체지향 언어이다.

object Hello {

def main(args:Array[String]) {

println(“Hello, World”)

}

}

Page 27: Scala overview

26

Pure O.O.

// Every value is an object

1.toString

// Every operation is a method call

1 + 2 + 3 (1).+(2).+(3)

// Can omit . and ( )

"abc" charAt 1 "abc".charAt(1)

Page 28: Scala overview

27

Classes

// Classes (and abstract classes) like Java

abstract class Language(val name:String) {

override def toString = name

}

// Example implementations

class Scala extends Language("Scala")

// Anonymous class

val scala = new Language("Scala") { /* empty */ }

Page 29: Scala overview

28

Case Classes

case class Person(firstName: String = "Jamie", lastName: String = "Allen") val jamieDoe = Person(lastName = "Doe") // Person(Jamie,Doe) abstract class Tree case class Sum(l: Tree, r: Tree) extends Tree case class Var(n: String) extends Tree case class Const(v: Int) extends Tree … type Environment = String => Int def eval(t: Tree, env: Environment): Int = t match { case Sum(l, r) => eval(l, env) + eval(r, env) case Var(n) => env(n) case Const(v) => v }

Data Transfer Objects (DTOs) done right

By default, class arguments are immutable & public

Should never be extended

Provide equals(), copy(), hashCode() and toString() implementations

Don’t have to use new keyword to create instances

Named Parameters and Default arguments give us Builder pattern semantics

Page 30: Scala overview

29

Traits

// Like interfaces in Java

trait Language {

val name:String

// But allow implementation

override def toString = name

}

Page 31: Scala overview

30

Traits

trait JVM {

override def toString = super.toString+" runs on JVM" }

trait Static {

override def toString = super.toString+" is Static" }

// Traits are stackable

class Scala extends Language with JVM with Static {

val name = "Scala"

}

println(new Scala) "Scala runs on JVM is Static"

Page 32: Scala overview

31

Objects

object Bootstrapper extends App { Person.createJamieAllen } object Person { def createJamieAllen = new Person("Jamie", "Allen") def createJamieDoe = new Person("Jamie", "Doe") val aConstantValue = "A constant value” } class Person(val firstName: String, val lastName: String)

Singletons within a JVM process No private constructor histrionics Companion Objects, used for factories and constants

Page 33: Scala overview

32

Tuples

def getNameAndAge: Tuple2[String, Int] = { val name = “Steve” val age = 30 (name, age) } val (name, age) = getNameAndAge println(“Name: “+ name) // Name: Steve println(“Age: “ + age) // Age: 30 val scalet = (“Scalet”, 27, “Seoul”) // scalet: (String, Int, String) = (“Scalet”, 27, “Seoul”) println(“Address: “ + scalet._3) // Address: Seoul

Tuple is a generalization of that: a collection of two, three, four, and more values Tuple can hold objects with different types but they are also immutable

Page 34: Scala overview

33

Scala는 함수형 언어이다.

object Hello {

def main(args:Array[String]) {

println(“Hello, World”)

}

}

Page 35: Scala overview

34

g(f(X))

Page 36: Scala overview

35

Characteristic Imperative Functional

Programmer focus How to perform tasks (algorithms) and how to track changes in state.

What information is desired and what transformations are required.

State Changes Important. Non-existent.

Order of execution Important. Low importance.

Primary flow control Loops, conditionals, and function (method) calls

Function calls, including recursion.

Primary manipulation unit Instances of structures or classes.

Functions as first-class objects and data collections.

Imperative Style vs. Functional Style

출처: http://msdn.microsoft.com/en-us/library/bb669144.aspx

Page 37: Scala overview

36

Function Type + Function Literal

// Type

(Int, Int)=>Int

// Literal

(x:Int, y:Int) => x + y

Page 38: Scala overview

37

First Class Functions

// Lightweight anonymous functions (x:Int, y:Int) => x + y // Calling the anonymous function val add = (x:Int, y:Int) => x + y val add : (Int, Int) => Int = (x:Int, y:Int) => x + y val add : (Int, Int) => Int = _ + _ val add = new Function2[Int, Int, Int] { def apply(x:Int, y:Int):Int = x + y } add(5,1) 6 add.apply(5,1) 6

Function name Argument List Function expression

어떤 함수가 다음 조건을 만족하면 일급 함수로 간주한다. 1. 변수나 데이터 구조안에 담을 수 있다. 2. 파라미터로 전달 할 수 있다. 3. 반환값(return value)으로 사용할 수 있다. 4. 할당에 사용된 이름과 관계없이 고유한 구별이 가능하다.

어떤 함수가 다음 조건을 만족하면 일급 함수로 간주한다. 1. 변수나 데이터 구조안에 담을 수 있다. 2. 파라미터로 전달 할 수 있다. 3. 반환값(return value)으로 사용할 수 있다. 4. 할당에 사용된 이름과 관계없이 고유한 구별이 가능하다.

출처: http://en.wikipedia.org/wiki/First-class_function

Page 39: Scala overview

38

Closures

// plusFoo can reference any values/variables in scope

var foo = 1

val plusFoo = (x:Int) => x + foo

plusFoo(5) 6

// Changing foo changes the return value of plusFoo

foo = 5

plusFoo(5) 10

Page 40: Scala overview

39

Pattern Matching

def what(any:Any) = any match {

case i:Int => "It's an Int"

case s:String => "It's a String"

case _ => "I don't know what it is"

}

what(123) "It's an Int"

what("hello") "It's a String"

what(false) "I don't know what it is"

Page 41: Scala overview

40

Pattern Matching

val nums = List(1,2,3)

// Pattern matching to create 3 vals

val List(a,b,c) = nums

a 1

b 2

c 3

Page 42: Scala overview

41

Immutable Types

// Immutable types by default

var nums = Set(1,2,3)

nums += 4 nums = nums.+(4)

// Mutable types available

import scala.collection.mutable._

val nums = Set(1,2,3)

nums += 4 nums.+=(4)

Page 43: Scala overview

42

Referential Transparency

// Transparent val example1 = "jamie".reverse val example2 = example1.reverse println(example1 + example2) // eimajjamie // Opaque val example1 = new StringBuffer("Jamie").reverse val example2 = example1.reverse println(example1 append example2) // jamiejamie

An expression is transparent if it can be replaced by its VALUE without changing the behavior of the program

In math, all functions are referentially transparent

Page 44: Scala overview

43

Scala Collections

val myMap = Map(1 -> "one", 2 -> "two", 3 -> "three") val mySet = Set(1, 4, 2, 8) val myList = List(1, 2, 8, 3, 3, 4) val myVector = Vector(1, 2, 3...)

You have the choice of mutable or immutable collection instances, immutable by default

Rich implementations, extremely flexible

Page 45: Scala overview

44

Rich Collection Functionality

val numbers = 1 to 20 // Range(1, 2, 3, ... 20) numbers.head // Int = 1 numbers.tail // Range(2, 3, 4, ... 20) numbers.take(5) // Range(1, 2, 3, 4, 5) numbers.drop(5) // Range(6, 7, 8, ... 20)

There are many methods available to you in the Scala collections library

Spend 5 minutes every day going over the ScalaDoc for one collection class

Page 46: Scala overview

45

scala.collection

Page 47: Scala overview

46

scala.collection.immutable

Page 48: Scala overview

47

scala.collection.mutable

Page 49: Scala overview

48

Or Use Existing Java Collections

java.util

Apache Commons Collections

fastutil

Trove

Google Collections

scala.collection.JavaConversion available to convert to and from java.util Interfaces

Page 50: Scala overview

49

Higher Order Functions

val plusOne = (x:Int) => x + 1

val nums = List(1,2,3)

// map takes a function: Int => T

nums.map(plusOne) List(2,3,4)

// Inline Anonymous

nums.map(x => x + 1) List(2,3,4)

// Short form

nums.map(_ + 1) List(2,3,4)

Page 51: Scala overview

50

Higher Order Functions

val nums = List(1,2,3,4)

// A few more examples for List class

nums.exists(_ == 2) true

nums.find(_ == 2) Some(2)

nums.indexWhere(_ == 2) 1

nums.reduceLeft(_ + _) 10

nums.foldLeft(100)(_ + _) 110

nums.filter(_ % 2 == 0) List(2,4)

// Many more in collections library

flatMap, flatten, zip, fold, foldRight, reduce, reduceRight, groupBy

partition, slice, take, takeRight, takeWhile, drop, dropRight, dropWhile, splitAt

sortBy, sortWith, startsWith, endsWith, product, sum …

Page 52: Scala overview

51

Higher Order Functions

// functions as parameters

def call(f: Int => Int) = f(1)

call(plusOne) 2

call(x => x + 1) 2

call(_ + 1) 2

Page 53: Scala overview

52

Higher Order Functions

// functions as parameters

def each(xs: List[Int], fun: Int => Unit) {

if(!xs.isEmpty) {

fun(xs.head)

each(xs.tail, fun)

}

}

each(List(1,2,3), println)

1

2

3

Page 54: Scala overview

53

Higher Order Functions

// More complex example with generics & pattern matching

@tailrec

def each[T](xs: List[T], fun: T => Unit): Unit = xs match {

case Nil =>

case head :: tail => fun(head); each(tail, fun)

}

each(List(1,2), println)

1

2

each(List("foo", "bar"), println)

foo

bar

class List[+A] … { def head: A def tail: List[A] … }

Page 55: Scala overview

54

Parallel Collections

scala> 1 to 1000000 res0: scala.collection.immutable.Range.Inclusive = Range(1, 2, 3,... scala> res0.par res1: s.c.parallel.immutable.ParRange = ParRange(1, 2, 3,... scala> res1 map(_ + 1) res2: s.c.parallel.immutable.ParSeq[Int] = ParVector(2, 3, 4,... scala> res2.seq res3: s.c.immutable.Range = Range(2, 3, 4,...

You can easily parallelize the application of a function literal to your collection by calling the par() method on a collection instance

Uses JSR166 under the covers to fork/join for you

Use the seq() method on the parallel collection to return to a non-parallel instance

Page 56: Scala overview

55

Partial Functions

val sample = 1 to 10 val isEven: PartialFunction[Int, String] = { case x if x % 2 == 0 => x+" is even" } val isEven= new PartialFunction[Int, String] { override def apply(x:Int):String = x+" is even" override def isDefinedAt(x:Int):Boolean = x % 2 == 0 } // the method collect can use isDefinedAt to select which members to collect val evenNumbers = sample collect isEven > evenNumbers = Vector(2 is even, 4 is even, 6 is even, 8 is even, 10 is even) val isOdd: PartialFunction[Int, String] = { case x if x % 2 == 1 => x+" is odd" } // the method orElse allows chaining another partial function to handle // input outside the declared domain val numbers = sample map (isEven orElse isOdd) > numbers = Vector(1 is odd, 2 is even, 3 is odd, 4 is even, 5 is odd, 6 is even, 7 is odd, 8 is even, 9 is odd, 10 is even)

Page 57: Scala overview

56

Currying

// multiple arguments def add(x:Int, y:Int) = x + y add(1, 2) // 3 add(7, 3) // 10 // after currying, single arguments def add(x:Int) = (y:Int) => x + y def add(x:Int)(y:Int) = x + y add(1)(2) // 3 add(7)(3) // 10

In computer science, currying, invented by Moses Schönfinkel and Gottlob Frege, is the technique of transforming a function that takes multiple arguments into a function that takes a single argument (the other arguments having been specified by the curry).

Page 58: Scala overview

57

Partially Applied Functions

def justSum(a:Int,b:Int,c:Int) = a+b+c val partial1 = justSum _ val partial2 = justSum(1, _:Int, 8) def curriedSum(a:Int)(b:Int)(c:Int) = a+b+c println("Partial 1: "+partial1(5,6,7)) // Partial 1: 18 println("Partial 2: "+partial2(4)) // Partial 2: 13

Page 59: Scala overview

58

Scala는 동적 언어이다.

(엄밀히 말하자면 동적 언어는 아니지만, 동적 언어에서 제공하는 많은 특징을 가지고 있다.)

object Hello {

def main(args:Array[String]) {

println(“Hello, World”)

}

}

Page 60: Scala overview

59

Scriptable

// HelloWorld.scala

println("Hello World")

bash$ scala HelloWorld.scala

Hello World

bash$ scala -e 'println("Hello World")'

Hello World

Page 61: Scala overview

60

Read-Eval-Print Loop

bash$ scala

Welcome to Scala version 2.8.1.final (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_22).

Type in expressions to have them evaluated.

Type :help for more information.

scala> class Foo { def bar = "baz" }

defined class Foo

scala> val f = new Foo

f: Foo = Foo@51707653

scala> f.bar

res2: java.lang.String = baz

Page 63: Scala overview

62

Implicit Conversions

// Extend existing classes in a type safe way

// Goal: Add isBlank method to String class

class RichString(s:String) {

def isBlank = null == s || "" == s.trim

}

implicit def toRichString(s:String) = new RichString(s)

// Our isBlank method is now available on Strings

" ".isBlank true

"foo".isBlank false

Page 64: Scala overview

63

Implicit Conversions

// Does not type check

"abc".isBlank

// Search in-scope implicits defs that take a

// String & return a type with an isBlank method

implicit def toRichString(s:String):RichString

// Resulting code that type checks

new RichString("abc").isBlank

Page 65: Scala overview

64

method_missing (Scala 2.9 Feature)

// Dynamic is a marker trait used by the compiler

class Foo extends Dynamic {

def typed[T] = error("not implemented")

def applyDynamic(name:String)(args:Any*) = {

println("called: "+name+"("+args.mkString(",")+")")

}

}

val f = new Foo

f.helloWorld called: helloWorld()

f.hello("world") called: hello(world)

f.bar(1,2,3) called: bar(1,2,3)

Page 66: Scala overview

65

Scala는 정적으로 타입화된 언어이다.

object Hello {

def main(args:Array[String]) {

println(“Hello, World”)

}

}

Page 67: Scala overview

66

Generic Classes

class Stack[T] {

var elems: List[T] = Nil

def push(x: T) { elems = x :: elems }

def top: T = elems.head

def pop() { elems = elems.tail }

}

object GenericsTest extends Application {

val stack = new Stack[Int]

stack.push(1)

stack.push('a')

println(stack.top) // 97

stack.pop()

println(stack.top) // 1

}

출처: http://www.scala-lang.org/node/113

Page 68: Scala overview

67

Variances

class Animal

class Dog extends Animal

class Vector[+T] { … }

class Contravariant[-T] {…}

class Array[T] {…}

val aCovariantVector: Vector[Animal] = Vector.empty[Animal] // ok

val aCovariantVector: Vector[Animal] = Vector.empty[Dog] // ok

val aCovariantVector: Vector[Dog] = Vector.empty[Animal] // not ok

val contravariantClass: Contravariant[Animal] = new Contravariant[Animal] // ok

val contravariantClass: Contravariant[Dog] = new Contravariant[Animal] // ok

val contravariantClass: Contravariant[Animal] = new Contravariant[Dog] // not ok

val anInvariantArray: Array[Animal] = Array.empty[Animal] // ok

val anInvariantArray: Array[Animal] = Array.empty[Dog] // not ok

val anInvariantArray: Array[Dog] = Array.empty[Animal] // not ok

출처: http://www.scala-lang.org/node/129

구분 Scala Java Description

Covariant +T ? extends T Covariant subclassing. E.g., List[Tsub] is a subtype of List[T].

Contravariant -T ? super T Contravariant subclassing. E.g., X[Tsup] is a subtype of X[T].

Invariant T T Invariant subclassing. E.g., Can’t substitute Y[Tsup]or Y[Tsub] for Y[T].

Page 69: Scala overview

68

Type Bounds (Upper, Lower)

object Array {

...

def apply[A <: AnyRef](xs: A*): Array[A] = { // A must be a subtype of AnyRef

val array = new Array[A](xs.length)

var i = 0

for (x <- xs.elements) { array(i) = x; i += 1 }

array

}

...

}

class List[+A] { // A is covariant, List[+A] is subtype of List[A]

...

def ::[B >: A](x : B) : List[B] = new scala.::(x, this) // B must be a supertype of A

...

}

val languages = List("Scala", "Java", "Ruby", "C#", "C++", "Python") // languages:List[String] = List(…)

val list = 3.14 :: languages // list:List[Any] = List (…)

println(list) // List(3.14, “Scala”, “Java”, “Ruby”, “C#”, “C++”, “Python”)

출처: http://www.scala-lang.org/node/136

구분 Scala Java Description

Upper Bounds A <: B A extends B A must be a subtype of B

Lower Bounds A >: B - A must be a supertype of B

Page 70: Scala overview

69

Views

Implicit parameters and methods can also define implicit conversions called views.

The term view conveys the sense of having a view from one type (A) to another type (B).

A view is applied in two circumstances.

When a type A is used in a context where another type B is expected and there is a view in scope that can convert A to B.

When a non-existent member m of a type A is referenced, but there is an in-scope view that can convert A to a B that has the m member.

def m [A <% B](arglist): R = ...

def m [A](arglist)(implicit viewAB: A => B): R = ...

class Container[A <% Int] { def addIt(x: A) = 123 + x }

(new Container[String]).addIt("123") // ok, 246

(new Container[Int]).addIt(123) // ok, 246

(new Container[Float]).addIt(123.2F) // not ok

출처: http://www.scala-lang.org/node/130

구분 Scala Java Description

View Bounds A <% B - A can be converted to B using a view

Page 71: Scala overview

70

Inner Classes

1. Use Companion Objects: object Graph for class Graph

2. Use Type Projection: Graph#Node is “a Node of any Graph”

출처: http://www.scala-lang.org/node/115, http://weblogs.java.net/blog/cayhorstmann/archive/2011/08/05/inner-classes-scala-and-java

class Graph { class Node { var connectedNodes: List[Node] = Nil def connectTo(node: Node) { if (connectedNodes.find(node.equals).isEmpty) { connectedNodes = node :: connectedNodes } } } var nodes: List[Node] = Nil def newNode: Node = { val res = new Node nodes = res :: nodes res } } object IllegalGraphTest extends Application { val g: Graph = new Graph val n1: g.Node = g.newNode val n2: g.Node = g.newNode n1.connectTo(n2) // legal val h: Graph = new Graph val n3: h.Node = h.newNode n1.connectTo(n3) // illegal! }

class Graph { class Node { var connectedNodes: List[Node] = Nil def connectTo(node: Node) { if (connectedNodes.find(node.equals).isEmpty) { connectedNodes = node :: connectedNodes } } } var nodes: List[Node] = Nil def newNode: Node = { val res = new Node nodes = res :: nodes res } } object IllegalGraphTest extends Application { val g: Graph = new Graph val n1: g.Node = g.newNode val n2: g.Node = g.newNode n1.connectTo(n2) // legal val h: Graph = new Graph val n3: h.Node = h.newNode n1.connectTo(n3) // illegal! }

object Graph { class Node { var connectedNodes: List[Node] = Nil def connectTo(node: Node) { if (connectedNodes.find(node.equals).isEmpty) { connectedNodes = node :: connectedNodes } } } } class Graph { var nodes: List[Graph.Node] = Nil def newNode: Node = { val res = new Node nodes = res :: nodes res } }

object Graph { class Node { var connectedNodes: List[Node] = Nil def connectTo(node: Node) { if (connectedNodes.find(node.equals).isEmpty) { connectedNodes = node :: connectedNodes } } } } class Graph { var nodes: List[Graph.Node] = Nil def newNode: Node = { val res = new Node nodes = res :: nodes res } }

class Graph { class Node { var connectedNodes: List[Graph#Node] = Nil def connectTo(node: Graph#Node) { if (connectedNodes.find(node.equals).isEmpty) { connectedNodes = node :: connectedNodes } } } … }

class Graph { class Node { var connectedNodes: List[Graph#Node] = Nil def connectTo(node: Graph#Node) { if (connectedNodes.find(node.equals).isEmpty) { connectedNodes = node :: connectedNodes } } } … }

Use Companion Objects

Use Type Projection

Page 72: Scala overview

71

Abstract Types

abstract class Buffer[+T] {

val element: T

}

abstract class SeqBuffer[U, +T <: Seq[U]] extends Buffer[T] {

def length = element.length

}

object AbstractTypeTest2 extends Application {

def newIntSeqBuf(e1: Int, e2: Int): SeqBuffer[Int, Seq[Int]] =

new SeqBuffer[Int, List[Int]] {

val element = List(e1, e2)

}

val buf = newIntSeqBuf(7, 8)

println("length = " + buf.length) // length = 2

println("content = " + buf.element) // content = List(7, 8)

}

출처: http://www.scala-lang.org/node/105

Page 73: Scala overview

72

Explicitly Typed Self References

abstract class SubjectObserver {

type S <: Subject // S must be a subtype of Subject

type O <: Observer // O must be a subtype of Observer

trait Subject {

self: S => // #1. val self: SubjectObserver.this.S

private var observers = List[O]()

def addObserver(observer: O) = observers ::= observer

def notifyObservers = observers foreach (_.receiveUpdate(self)) // #2

}

trait Observer {

def receiveUpdate(subject: S)

}

}

- Comment #1 shows the self-type annotation, self: S =>. We can now use self as an alias for this, but whenever it appears, the type will be assumed to be S, not Subject.

- Comment #2 shows that we pass self instead of this to receiveUpdate.

출처: http://www.scala-lang.org/node/124

Page 74: Scala overview

73

Polymorphic Methods

object PolyTest extends Application {

def dup[T](x: T, n: Int): List[T] =

if (n == 0) Nil

else x :: dup(x, n - 1)

println(dup[Int](3, 4)) // required parameters

println(dup("three", 3)) // not required to give actual type parameters explicitly

}

Method dup in object PolyTest is parameterized with type T and with the value parameters x: T and n: Int

출처: http://www.scala-lang.org/node/121

Page 75: Scala overview

74

Scala는 많은 좋은 기능이 있다.

object Hello {

def main(args:Array[String]) {

println(“Hello, World”)

}

}

Page 76: Scala overview

75

Default Parameter Values

def hello(foo:Int = 0, bar:Int = 0) {

println("foo: "+foo+" bar: "+bar)

}

hello() foo: 0 bar: 0

hello(1) foo: 1 bar: 0

hello(1,2) foo: 1 bar: 2

Page 77: Scala overview

76

Named Parameters

def hello(foo:Int = 0, bar:Int = 0) {

println("foo: "+foo+" bar: "+bar)

}

hello(bar=6) foo: 0 bar: 6

hello(foo=7) foo: 7 bar: 0

hello(foo=8,bar=9) foo: 8 bar: 9

Page 78: Scala overview

77

Everything Returns a Value

val a = if(true) "yes" else "no"

val b = try{

"foo"

} catch {

case _ => "error"

}

val c = {

println("hello")

"foo"

}

Page 79: Scala overview

78

Lazy Definitions

// initialized on first access

lazy val foo = {

println("init")

"bar"

}

foo init

foo

foo

Page 80: Scala overview

79

Nested Functions

// Can nest multiple levels of functions

def outer() {

var msg = "foo"

def one() {

def two() {

def three() {

println(msg)

}

three()

}

two()

}

one()

}

Page 81: Scala overview

80

By-Name Parameters

// msg parameter automatically wrapped in closure

def log(doLog:Boolean, msg: => String) {

if(doLog) {

msg // evaluates msg

msg // evaluates msg again!

}

}

def foo:String = {

println("in foo"); "Foo"

}

log(true, foo+" Bar") // foo called twice

in foo

in foo

log(false, foo+" Bar") // foo never called

Page 82: Scala overview

81

Many More Features

Annotations @foo def hello = "world"

Option

Actors

DSL

For Comprehensions for(i <- 1 to 5 if i % 2 == 0) yield i

Implicit Conversion

XML Literals val node = <hello>world</hello>

Reflections

Macros (2.10)

etc…

Page 83: Scala overview

82

Scala를 어떻게 공부하지?

object Hello {

def main(args:Array[String]) {

println(“Hello, World”)

}

}

Page 84: Scala overview

83

Scala 공부의 정석

Page 85: Scala overview

84

Martin Ordersky 저자 강의

https://www.coursera.org/course/progfun

Page 86: Scala overview

85

Typesafe

http://www.typesafe.com

Page 88: Scala overview

87

Scala 공부관련 참고자료

스칼라 입문자료 – Scala API Reference – A Tour of Scala : 스칼라 공식 블로그에 올라온 스칼라 강좌 – Scala By Example : 마틴 오더스키가 작성한 100페이지짜리 스칼라 문서 – Scala School : 트위터가 작성한 스칼라 강좌 – Progammin in Scala 1st Edition : Programmin in Scala의 1st Edition은 온라인에서 무료로 볼

수 있음. – Effective Scala : 트위터의 Marius Eriksen가 만든 스칼라 강좌

스칼라 서적(영문) – Programming in Scala : 마틴 오더스키가 참여한 스칼라 서적. 강추!!, Scala 2.8 기준. – Programming Scala : 오렐리에서 나옴. 읽어본 사람 없어서 내용은 잘 모름. – Programming Scala : Pragmatic에서 나온 스칼라 서적. 읽어볼 만은 하지만 빠진 내용이 많아

서 많이 추천하지는 않음. – Scala in Depth : 매닝에서 나온 서적. 읽어본 사람이 없어서 내용은 잘 모름.

그외 참고 자료 – Style Guide for Scala : 스칼라 코드 작성에 대한 스타일가이드 발표자료 – Scala Puzzlers : 스칼라 문제를 풀어볼 수 있는 사이트 – Scala Cheat Sheet : 간단한 스칼라문법을 참고할 수 있는 치트시트 – S99 Scala Problems: 99 개의 스칼라 프로그래밍 학습 예제