• Like
  • Save
[H3 2012] 꽃보다 Scala
Upcoming SlideShare
Loading in...5
×
 

[H3 2012] 꽃보다 Scala

on

  • 3,084 views

H3 2012 발표자료

H3 2012 발표자료
꽃보다 Scala
-KTH 김상범

Statistics

Views

Total Views
3,084
Views on SlideShare
2,135
Embed Views
949

Actions

Likes
28
Downloads
145
Comments
0

8 Embeds 949

http://h3.kthcorp.com 911
http://h3.paran.com 11
http://play.daumcorp.com 9
http://h3.localhost.com 6
http://tedwon.com 6
http://115.68.2.182 4
http://211.62.44.161 1
https://www.linkedin.com 1
More...

Accessibility

Categories

Upload Details

Uploaded via as Apple Keynote

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n

[H3 2012] 꽃보다 Scala [H3 2012] 꽃보다 Scala Presentation Transcript

  • 꽃보다Scala !김상범 | @taokim
  • “만약, 2003년경에 누군가 나에게 Programming in Scala 라는 책을 보여줬다면 나는 절대로 Groovy를 만들지 않았을 것이다 ” James Strachan, the creator of Groovy
  • TOC1. Scala?2. Functional Style3. Pattern Matching4. Horizontal Scale
  • Scala?
  • Scala?object HelloWorld { def main(args:Array[String]){ println("Hello, world!") }}
  • Scala?
  • Scala?Quick Scala Facts
  • Scala? Quick Scala FactsJVM/.NET 에서 구동되는 범용 multi-paradigm 언어
  • Scala? Quick Scala FactsJVM/.NET 에서 구동되는 범용 multi-paradigm 언어Created by Martin Odersky
  • Scala? Quick Scala Facts JVM/.NET 에서 구동되는 범용 multi-paradigm 언 어 Created by Martin Odersky✓ EPFL 의 교수
  • Scala? Quick Scala Facts JVM/.NET 에서 구동되는 범용 multi-paradigm 언 어 Created by Martin Odersky✓ EPFL 의 교수✓ javac(Sun’s java compiler)
  • Scala? Quick Scala Facts JVM/.NET 에서 구동되는 범용 multi-paradigm 언 어 Created by Martin Odersky✓ EPFL 의 교수✓ javac(Sun’s java compiler)✓ Generic Java (“make Java better”)
  • Scala? Quick Scala Facts JVM/.NET 에서 구동되는 범용 multi-paradigm 언 어 Created by Martin Odersky✓ EPFL 의 교수✓ javac(Sun’s java compiler)✓ Generic Java (“make Java better”)✓ Since 2001
  • Scala? Quick Scala Facts JVM/.NET 에서 구동되는 범용 multi-paradigm 언 어 Created by Martin Odersky✓ EPFL 의 교수✓ javac(Sun’s java compiler)✓ Generic Java (“make Java better”)✓ Since 2001 => 최신 안정화 버전 : 2.9.2 final (2012/04/14)
  • Scala? Quick Scala Facts JVM/.NET 에서 구동되는 범용 multi-paradigm 언 어 Created by Martin Odersky✓ EPFL 의 교수✓ javac(Sun’s java compiler)✓ Generic Java (“make Java better”)✓ Since 2001 => 최신 안정화 버전 : 2.9.2 final (2012/04/14) => 개발 버전 : 2.10.0 RC1 (2012/10/19)
  • Scala?
  • Scala?Quick Scala Facts
  • Scala? Quick Scala Facts더 짧고 더 명료한 코드
  • Scala? Quick Scala Facts더 짧고 더 명료한 코드강력한 표현력과 DSL을 통한 확장성
  • Scala? Quick Scala Facts더 짧고 더 명료한 코드강력한 표현력과 DSL을 통한 확장성Java 와의 상호 운영성
  • Scala? Quick Scala Facts더 짧고 더 명료한 코드강력한 표현력과 DSL을 통한 확장성Java 와의 상호 운영성강력한 정적 타입 시스템
  • Scala? Quick Scala Facts더 짧고 더 명료한 코드강력한 표현력과 DSL을 통한 확장성Java 와의 상호 운영성강력한 정적 타입 시스템객체 지향과 함수형 스타일을 모두 지원
  • Scala? Quick Scala Facts더 짧고 더 명료한 코드강력한 표현력과 DSL을 통한 확장성Java 와의 상호 운영성강력한 정적 타입 시스템객체 지향과 함수형 스타일을 모두 지원동일한 목적의 자바 코드와 동일한 성능
  • Scala? Quick Scala Facts더 짧고 더 명료한 코드강력한 표현력과 DSL을 통한 확장성Java 와의 상호 운영성강력한 정적 타입 시스템객체 지향과 함수형 스타일을 모두 지원동일한 목적의 자바 코드와 동일한 성능광범위한 상업적 적용
  • Scala? Quick Scala Facts더 짧고 더 명료한 코드강력한 표현력과 DSL을 통한 확장성Java 와의 상호 운영성강력한 정적 타입 시스템객체 지향과 함수형 스타일을 모두 지원동일한 목적의 자바 코드와 동일한 성능광범위한 상업적 적용강력한 동시성 처리
  • Scala? Less code 표현의 간결함 자바에 비해 코드 사이즈가 1/3 ~2/3 정도로 감소함 절반의 코드는✓ 코드를 이해하는데 절반의 시간이 필요함을 뜻하며✓ 버그의 가능성 역시 절반으로 감소함
  • A class... class Person(val name: String, val age: Int)class Person { public final String name; public final int age; public Person(String name, int age) { this.name = name; this.age = age; }}
  • VO/POJOclass Person { private final String name; case class Person(name: String, private final int age; age: Int) public Person(String name, int age) { super(); this.name = name; this.age = age; } public String getName() { return name; } public int getAge() { return age; } @Override public boolean equals(Object other) { if (this == other) { return true; } else if (other instanceof Person) { Person p = (Person) other; return name == null ? p.name == null : name.equals(p.name) && age == p.age; } else { return false; } } @Override public int hashCode() { int h = name == null ? 0 : name.hashCode(); return 39 * h + age; } @Override public String toString() { return new StringBuilder("Person(").append(name).append(",").append(age) .append(")").toString(); }}
  • Scala?
  • Scala?Great interoperability with Java
  • Scala?Great interoperability with JavaScala는 자바와 소스 코드 레벨에서만 다름
  • Scala?Great interoperability with JavaScala는 자바와 소스 코드 레벨에서만 다름컴파일되면 “.class” 파일이 나옴
  • Scala?Great interoperability with JavaScala는 자바와 소스 코드 레벨에서만 다름컴파일되면 “.class” 파일이 나옴Scala코드에서 Java클래스를 그대로 import 해서 사용
  • Scala?Great interoperability with JavaScala는 자바와 소스 코드 레벨에서만 다름컴파일되면 “.class” 파일이 나옴Scala코드에서 Java클래스를 그대로 import 해서 사용한 프로젝트에서 Java와 Scala 파일을 섞어서 사용 가능
  • Scala?Great interoperability with JavaScala는 자바와 소스 코드 레벨에서만 다름컴파일되면 “.class” 파일이 나옴Scala코드에서 Java클래스를 그대로 import 해서 사용한 프로젝트에서 Java와 Scala 파일을 섞어서 사용 가능Java 가 지원되는 어떤 환경/클라우드에도 배포 가능
  • Scala?Great interoperability with JavaScala는 자바와 소스 코드 레벨에서만 다름컴파일되면 “.class” 파일이 나옴Scala코드에서 Java클래스를 그대로 import 해서 사용한 프로젝트에서 Java와 Scala 파일을 섞어서 사용 가능Java 가 지원되는 어떤 환경/클라우드에도 배포 가능그리고 Android ~
  • Great interoperability with Javaimport java.net._import java.io._val u = new URL( "http://www.scala-lang.org/")val in = u.openStream()val br = new BufferedReader( new InputStreamReader(in))
  • Popularity and Use Grow Commercial Adoptions Twitter✓ 메시지 패싱 시스템을 Ruby에서 Scala 기반으로 변경✓ Finagle, Gizzard, Kestrel, ... Linked-in✓ 소셜 그래프 서비스 (380-400M transaction/day)✓ Apache Kafka Foursquare✓ 웹을 포함한 모든 서비스가 Scala로 작성됨 Tumblr✓ 분산 시스템을 위해 Finagle 선택
  • Programming Language Popularity 1 JavaScript 2 Java 3 PHP 4 Python 5 Ruby 6 C# 7 C++ 8 C 9 Objective-C 10 Shell 11 Perl 12 Scala 13 Haskell 14 ASP 15 Assembly 16 ActionScript 17 R 18 VisualBasic 19 CoffeeScript 20 Groovy출처: http://redmonk.com/sogrady/2012/09/12/language-rankings-9-12/
  • Scala Job trends출처: http://www.indeed.com/jobtrends/scala.html
  • 근데,어렵진 않나요?...
  • LISP, Haskell, Erlang, Clojure 등의 함수형 언어에 익숙하다면 쉽습니다
  • Ruby, Python, Javascript 등의 언어에 익숙하다면 어렵진 않을 겁니다 :)
  • 자바만주로 해오셨다면...
  • 불지옥을 보시게될지도 모릅니다 ...
  • 불지옥을 보시게될지도 모릅니다 ...
  • Problems of Java
  • Problems of Java자바코드 == 대하소설
  • Problems of Java 자바코드 == 대하소설✓ 제한된 vocabulary
  • Problems of Java 자바코드 == 대하소설✓ 제한된 vocabulary✓ 수 많은 third party 라이브러리 필수
  • Problems of Java 자바코드 == 대하소설✓ 제한된 vocabulary✓ 수 많은 third party 라이브러리 필수✓ 너무 적은 언어의 기능/개념
  • Problems of Java 자바코드 == 대하소설✓ 제한된 vocabulary✓ 수 많은 third party 라이브러리 필수✓ 너무 적은 언어의 기능/개념✓ Need more syntactic sugars!
  • Problems of Java 자바코드 == 대하소설✓ 제한된 vocabulary✓ 수 많은 third party 라이브러리 필수✓ 너무 적은 언어의 기능/개념✓ Need more syntactic sugars!
  • Problems of Java 자바코드 == 대하소설✓ 제한된 vocabulary✓ 수 많은 third party 라이브러리 필수✓ 너무 적은 언어의 기능/개념✓ Need more syntactic sugars! 이미 legacy, 너무 느린 발전 속도
  • Problems of Java 자바코드 == 대하소설✓ 제한된 vocabulary✓ 수 많은 third party 라이브러리 필수✓ 너무 적은 언어의 기능/개념✓ Need more syntactic sugars! 이미 legacy, 너무 느린 발전 속도 Oracle...
  • Functional Style think f(x)!
  • f(x)?
  • f(x)?
  • g(f(x))
  • Imperative vsFunctional
  • 명령형? Imperative style 우리에게 익숙한 그것 :)✓ C, C++, Java, ... 컴퓨터에게 절차적으로 명령을 내리는 방식✓ “x 와 y 를 더하고, 결과를 z에 담고, z를 화면에 출력” Advantages✓ 본질적으로 컴퓨터는 명령을 받고 수행하는 기계✓ 많은 프로그래밍 언어가 명령형이며, 수많은 개발자가 이 방식에 익숙함
  • 함수형?
  • 함수형?Functional style
  • 함수형? Functional style값의 변환 transformation 을 강조
  • 함수형? Functional style 값의 변환 transformation 을 강조✓ 값을 입력 받고 새로운 값을 리턴함
  • 함수형? Functional style 값의 변환 transformation 을 강조✓ 값을 입력 받고 새로운 값을 리턴함 변경 불가능한 상태 immutable state 를 강조
  • 함수형? Functional style 값의 변환 transformation 을 강조✓ 값을 입력 받고 새로운 값을 리턴함 변경 불가능한 상태 immutable state 를 강조✓ referentially transparent (e.g., java.lang.String)
  • 함수형? Functional style 값의 변환 transformation 을 강조✓ 값을 입력 받고 새로운 값을 리턴함 변경 불가능한 상태 immutable state 를 강조✓ referentially transparent (e.g., java.lang.String) 부수 효과 없음 no side-effects 을 강조
  • 함수형? Functional style 값의 변환 transformation 을 강조✓ 값을 입력 받고 새로운 값을 리턴함 변경 불가능한 상태 immutable state 를 강조✓ referentially transparent (e.g., java.lang.String) 부수 효과 없음 no side-effects 을 강조✓ 언제 계산 evaluation 을 하던, 같은 값을 리턴
  • 함수형?
  • 함수형?Functional style
  • 함수형? Functional style최상위 개념으로서의 함수 first-class function
  • 함수형? Functional style 최상위 개념으로서의 함수 first-class function✓ “function everywhere”
  • 함수형? Functional style 최상위 개념으로서의 함수 first-class function✓ “function everywhere” Advantages
  • 함수형? Functional style 최상위 개념으로서의 함수 first-class function✓ “function everywhere” Advantages✓ 본질적으로 병렬화가 가능하며 thread-safe 함
  • 함수형? Functional style 최상위 개념으로서의 함수 first-class function✓ “function everywhere” Advantages✓ 본질적으로 병렬화가 가능하며 thread-safe 함✓ Lazy evaluation 과 같은 최적화가 용이
  • 함수형? Functional style 최상위 개념으로서의 함수 first-class function✓ “function everywhere” Advantages✓ 본질적으로 병렬화가 가능하며 thread-safe 함✓ Lazy evaluation 과 같은 최적화가 용이✓ 함수를 연계하여, 코드를 좀 더 유연한 형태의 일반화 용이
  • 명령형 vs 함수형명령형 Imperative 함수형 Functional 명령 command 함수 function 문장 sentence 표현식 expression 변수 variable 값 value변경가능 mutable 변경불가 immutable 루프 loop 재귀 recursion
  • 명령형 vs 함수형 Scala?Scala 는 양쪽 스타일 모두를 지원문제의 영역 domain 에 맞는 방식을 선택일반적으로는 명령형보다 함수형을 권장
  • Imperative Style(Java) 전달된 리스트 자체를 바꾸기public static void addOneToAll(ArrayList<Integer> items){ for (int i = 0; i < items.size(); ++i) { items.set(i, items.get(i) + 1); }}
  • Functional Style(Java) 원본은 그대로 두고 새로운 List 를 리턴public static List<Integer> addOneToAll(List<Integer> items) { ArrayList<Integer> result = new ArrayList<Integer>(); for (int i : items) { result.add(i + 1); } return result;}
  • Functional Style(Java) Functional Enables Compositionpublic static List<Integer> addTwoToAll(List<Integer> items) { return addOneToAll(addOneToAll(items));}
  • Function in Scala
  • Function in Mathf(x) = x + 1
  • Function in Scaladef f(x:Int):Int = x+1
  • Function in Scala함수 인자 타입 def f(x:Int):Int = x+1
  • Function in Scala 함수의 계산 결 과 타입 (리턴타입)함수 인자 타입 def f(x:Int):Int = x+1
  • Function in Scala
  • Function in Scaladef f(x:Int) = x + 1
  • Function in Scaladef f(x:Int) = x + 1def g(x:Int) = x * x
  • Function in Scaladef f(x:Int) = x + 1def g(x:Int) = x * xdef h(x:String, y:Int) = x + y
  • Function in Scaladef f(x:Int) = x + 1def g(x:Int) = x * xdef h(x:String, y:Int) = x + y
  • Function in Scaladef f(x:Int) = x + 1def g(x:Int) = x * xdef h(x:String, y:Int) = x + y => 추론 가능한 타입 선언 생략 가능
  • Function in Scaladef f(x:Int) = x + 1def g(x:Int) = x * xdef h(x:String, y:Int) = x + y => 추론 가능한 타입 선언 생략 가능 => 첫 등장시에만 타입 선언
  • Function call in Scalah("result:", f(g(3)))
  • Anonymous function(λ expression) in Scala (x:Int) => x + 1(x:Int,y:Int) => x < y
  • Anonymous functionval people: List[Person]val minors = people.filter((p:Person) => p.age < 20)
  • Anonymous function : short formval people: List[Person]val minors = people.filter(p => p.age < 20)
  • Anonymous function : placeholderval people: List[Person]val minors = people.filter(_.age < 20)
  • addOneToAll in Scala Imperativedef addOneToAll(items: collection.mutable.ListBuffer[Int])= { var i = 0 while (i < items.length) { items.update(i, items(i) + 1) i += 1 }} Functionaldef addOneToAll(items: List[Int]) = items map (_ + 1)
  • Functional Style with Collection
  • Functional Style with Collectioncollection.map(f(x))
  • Functional Style with Collection collection.map(f(x))모든 collection 에 존재
  • Functional Style with Collection collection.map(f(x))모든 collection 에 존재함수 f 를 전달 받아 collection 의 각 item 에 f 를 적용
  • Functional Style with Collection collection.map(f(x))모든 collection 에 존재함수 f 를 전달 받아 collection 의 각 item 에 f 를 적용f 의 결과를 같은 사이즈의 같은 collection 에 담아 리턴
  • Functional Style with Collection collection.map(f(x)) 모든 collection 에 존재 함수 f 를 전달 받아 collection 의 각 item 에 f 를 적용 f 의 결과를 같은 사이즈의 같은 collection 에 담아 리턴scala> val strs = List("aaa", "bb", "c")
  • Functional Style with Collection collection.map(f(x)) 모든 collection 에 존재 함수 f 를 전달 받아 collection 의 각 item 에 f 를 적용 f 의 결과를 같은 사이즈의 같은 collection 에 담아 리턴scala> val strs = List("aaa", "bb", "c")strs: List[java.lang.String] = List(aaa, bb, c)
  • Functional Style with Collection collection.map(f(x)) 모든 collection 에 존재 함수 f 를 전달 받아 collection 의 각 item 에 f 를 적용 f 의 결과를 같은 사이즈의 같은 collection 에 담아 리턴scala> val strs = List("aaa", "bb", "c")strs: List[java.lang.String] = List(aaa, bb, c)scala> val ints = strs.map(str => str.length)
  • Functional Style with Collection collection.map(f(x)) 모든 collection 에 존재 함수 f 를 전달 받아 collection 의 각 item 에 f 를 적용 f 의 결과를 같은 사이즈의 같은 collection 에 담아 리턴scala> val strs = List("aaa", "bb", "c")strs: List[java.lang.String] = List(aaa, bb, c)scala> val ints = strs.map(str => str.length)ints: List[Int] = List(3, 2, 1)
  • Functional Style with Collection collection.map(f(x)) 모든 collection 에 존재 함수 f 를 전달 받아 collection 의 각 item 에 f 를 적용 f 의 결과를 같은 사이즈의 같은 collection 에 담아 리턴scala> val strs = List("aaa", "bb", "c")strs: List[java.lang.String] = List(aaa, bb, c)scala> val ints = strs.map(str => str.length)ints: List[Int] = List(3, 2, 1) String => Int
  • Functional Style with Collection collection.map(f(x)) 모든 collection 에 존재 함수 f 를 전달 받아 collection 의 각 item 에 f 를 적용 f 의 결과를 같은 사이즈의 같은 collection 에 담아 리턴scala> val strs = List("aaa", "bb", "c")strs: List[java.lang.String] = List(aaa, bb, c)scala> val ints = strs.map(str => str.length)ints: List[Int] = List(3, 2, 1) String => Int
  • Functional Style with Collection collection.map(f(x)) 모든 collection 에 존재 함수 f 를 전달 받아 collection 의 각 item 에 f 를 적용 f 의 결과를 같은 사이즈의 같은 collection 에 담아 리턴scala> val strs = List("aaa", "bb", "c")strs: List[java.lang.String] = List(aaa, bb, c)scala> val ints = strs.map(str => str.length)ints: List[Int] = List(3, 2, 1) String => Int
  • Functional Style with Collection collection.map(f(x)) 모든 collection 에 존재 함수 f 를 전달 받아 collection 의 각 item 에 f 를 적용 f 의 결과를 같은 사이즈의 같은 collection 에 담아 리턴scala> val strs = List("aaa", "bb", "c")strs: List[java.lang.String] = List(aaa, bb, c)scala> val ints = strs.map(str => str.length)ints: List[Int] = List(3, 2, 1) String => Int
  • Functional Style with Collection collection.map(f(x)) 모든 collection 에 존재 함수 f 를 전달 받아 collection 의 각 item 에 f 를 적용 f 의 결과를 같은 사이즈의 같은 collection 에 담아 리턴scala> val strs = List("aaa", "bb", "c")strs: List[java.lang.String] = List(aaa, bb, c)scala> val ints = strs.map(str => str.length)ints: List[Int] = List(3, 2, 1) String => Int
  • Functional Style with Collection collection.map(f(x)) 모든 collection 에 존재 함수 f 를 전달 받아 collection 의 각 item 에 f 를 적용 f 의 결과를 같은 사이즈의 같은 collection 에 담아 리턴scala> val strs = List("aaa", "bb", "c")strs: List[java.lang.String] = List(aaa, bb, c)scala> val ints = strs.map(str => str.length)ints: List[Int] = List(3, 2, 1) String => Int
  • Functional Style with Collection
  • Functional Style with Collectioncollection.reduce(f(x,y))
  • Functional Style with Collectioncollection.reduce(f(x,y))모든 collection 에 존재
  • Functional Style with Collectioncollection.reduce(f(x,y))모든 collection 에 존재collection 에 존재하는 값들을 하나의 값으로 만듬
  • Functional Style with Collection collection.reduce(f(x,y)) 모든 collection 에 존재 collection 에 존재하는 값들을 하나의 값으로 만듬scala> val nums = 1 to 5 //1.to(5)
  • Functional Style with Collection collection.reduce(f(x,y)) 모든 collection 에 존재 collection 에 존재하는 값들을 하나의 값으로 만듬scala> val nums = 1 to 5 //1.to(5)nums: Range.Inclusive = Range(1, 2, 3, 4, 5)
  • Functional Style with Collection collection.reduce(f(x,y)) 모든 collection 에 존재 collection 에 존재하는 값들을 하나의 값으로 만듬scala> val nums = 1 to 5 //1.to(5)nums: Range.Inclusive = Range(1, 2, 3, 4, 5)scala> val fact = nums.reduce((acc,num)=>acc*num)
  • Functional Style with Collection collection.reduce(f(x,y)) 모든 collection 에 존재 collection 에 존재하는 값들을 하나의 값으로 만듬scala> val nums = 1 to 5 //1.to(5)nums: Range.Inclusive = Range(1, 2, 3, 4, 5)scala> val fact = nums.reduce((acc,num)=>acc*num)fact: Int = 120
  • Functional Style with Collection collection.reduce(f(x,y)) 모든 collection 에 존재 collection 에 존재하는 값들을 하나의 값으로 만듬scala> val nums = 1 to 5 //1.to(5)nums: Range.Inclusive = Range(1, 2, 3, 4, 5)scala> val fact = nums.reduce((acc,num)=>acc*num)fact: Int = 120 (Int,Int)=> Int
  • reduce돌돌돌~ 말아 보아요~
  • reduce1 2 3 4
  • reduce11 2 2 3 4 1*2 2
  • reduce11 2 2 3 3 4 1*2 2 2 * 3 6
  • reduce11 2 2 3 3 4 4 1*2 2 2 * 3 6 6 * 4 24
  • reduce11 2 2 3 3 4 45 1*2 2 2 * 3 6 6 * 4 24 24 * 5 120
  • Functional Style: map reduce
  • Functional Style: map reduceval people :Array[Person] = ...
  • Functional Style: map reduceval people :Array[Person] = ...val sum = people.map(_.age).reduce(_ + _)
  • Functional Style: map reduceval people :Array[Person] = ...val sum = people.map(_.age).reduce(_ + _)val avg = sum / people.length
  • Functional Style: map reduceval people :Array[Person] = ...val sum = people.map(_.age).reduce(_ + _)val avg = sum / people.length scala> val people = Array(Person("Charles", 50),
  • Functional Style: map reduceval people :Array[Person] = ...val sum = people.map(_.age).reduce(_ + _)val avg = sum / people.length scala> val people = Array(Person("Charles", 50), | Person("G.Ne", 60), Person("Jane", 59)) people: Array[Person] = Array(Person(Charles,50), Person(G.Ne,60), Person(Jane,59))
  • Functional Style: map reduceval people :Array[Person] = ...val sum = people.map(_.age).reduce(_ + _)val avg = sum / people.length scala> val people = Array(Person("Charles", 50), | Person("G.Ne", 60), Person("Jane", 59)) people: Array[Person] = Array(Person(Charles,50), Person(G.Ne,60), Person(Jane,59)) scala> val ages = people.map(p => p.age)
  • Functional Style: map reduceval people :Array[Person] = ...val sum = people.map(_.age).reduce(_ + _)val avg = sum / people.length scala> val people = Array(Person("Charles", 50), | Person("G.Ne", 60), Person("Jane", 59)) people: Array[Person] = Array(Person(Charles,50), Person(G.Ne,60), Person(Jane,59)) scala> val ages = people.map(p => p.age) ages: Array[Int] = Array(50, 60, 59)
  • Functional Style: map reduceval people :Array[Person] = ...val sum = people.map(_.age).reduce(_ + _)val avg = sum / people.length scala> val people = Array(Person("Charles", 50), | Person("G.Ne", 60), Person("Jane", 59)) people: Array[Person] = Array(Person(Charles,50), Person(G.Ne,60), Person(Jane,59)) scala> val ages = people.map(p => p.age) ages: Array[Int] = Array(50, 60, 59) scala> ages.reduce((acc, age) => acc + age)
  • Functional Style: map reduceval people :Array[Person] = ...val sum = people.map(_.age).reduce(_ + _)val avg = sum / people.length scala> val people = Array(Person("Charles", 50), | Person("G.Ne", 60), Person("Jane", 59)) people: Array[Person] = Array(Person(Charles,50), Person(G.Ne,60), Person(Jane,59)) scala> val ages = people.map(p => p.age) ages: Array[Int] = Array(50, 60, 59) scala> ages.reduce((acc, age) => acc + age) res7: Int = 169
  • Functional Style: map reduceval people :Array[Person] = ...val sum = people.map(_.age).reduce(_ + _)val avg = sum / people.length scala> val people = Array(Person("Charles", 50), | Person("G.Ne", 60), Person("Jane", 59)) people: Array[Person] = Array(Person(Charles,50), Person(G.Ne,60), Person(Jane,59)) scala> val ages = people.map(p => p.age) 50 + 60 = 110 ages: Array[Int] = Array(50, 60, 59) 110 + 59 = 169 scala> ages.reduce((acc, age) => acc + age) res7: Int = 169
  • Functional style Functional is ... Just a pattern and NOT a syntax.✓ Java이냐 Scala 이냐 관계 없이 Functional 하게 코드를 작성 할 수 있음✓ Functional Java: => http://functionaljava.org/ => http://code.google.com/p/guava-libraries/ Not only for academic languages✓ Java를 제외한 Ruby, Python, Javascript 같은 대부분의 언어들은 functional style 을 위한 다양한 도구를 지원함
  • Pattern Matching
  • match/case
  • match/caseval new = old match { case 패턴1 => 값1 case 패턴2 => 값2 case _ => 기본값}
  • Pattern matching Matching on valuesval times = 1val numStr = times match { case 1 => "one" case 2 => "two" case _ => "some other number"}
  • Pattern matching Matching with guardsval times = 1val numStr = times match { case i if i == 1 => "one" case i if i == 2 => "two" case _ => "some other number"}
  • Pattern matching Matching on typedef bigger(o: Any): Any = { o match { case i: Int if i < 0 => i - 1 case i: Int => i + 1 case d: Double if d < 0.0 => d - 0.1 case d: Double => d + 0.1 case text: String => text + "s" }}
  • Pattern matching Matching on class memberclass Calculator(val brand: String, val model: String)def calcType(calc: Calculator) = calc match { case c if c.brand == "hp" && c.model == "20B" => "financial" case c if c.brand == "hp" && c.model == "48G" => "scientific" case c if c.brand == "hp" && c.model == "30B" => "business" case _ => "unknown"}
  • case classcase class Calculator(brand: String, model: String)
  • case classcase class Calculator(brand: String, model: String) accessor, equals(==), hashCode(##), toString, copy, pattern matching, factory function
  • case class
  • case classscala> val a = Calculator("hp", "20B")
  • case classscala> val a = Calculator("hp", "20B")a: Calculator = Calculator(hp,20B)
  • case classscala> val a = Calculator("hp", "20B")a: Calculator = Calculator(hp,20B)scala> a ##
  • case classscala> val a = Calculator("hp", "20B")a: Calculator = Calculator(hp,20B)scala> a ##res58: Int = 1619269961
  • case classscala> val a = Calculator("hp", "20B")a: Calculator = Calculator(hp,20B)scala> a ##res58: Int = 1619269961scala> a toString
  • case classscala> val a = Calculator("hp", "20B")a: Calculator = Calculator(hp,20B)scala> a ##res58: Int = 1619269961scala> a toStringres59: String = Calculator(hp,20B)
  • case classscala> val a = Calculator("hp", "20B")a: Calculator = Calculator(hp,20B)scala> a ##res58: Int = 1619269961scala> a toStringres59: String = Calculator(hp,20B)scala> a.copy(model = "48G")
  • case classscala> val a = Calculator("hp", "20B")a: Calculator = Calculator(hp,20B)scala> a ##res58: Int = 1619269961scala> a toStringres59: String = Calculator(hp,20B)scala> a.copy(model = "48G")res60: Calculator = Calculator(hp,48G)
  • case classscala> val a = Calculator("hp", "20B")a: Calculator = Calculator(hp,20B)scala> a ##res58: Int = 1619269961scala> a toStringres59: String = Calculator(hp,20B)scala> a.copy(model = "48G")res60: Calculator = Calculator(hp,48G)scala> val b = Calculator("hp", "20B")
  • case classscala> val a = Calculator("hp", "20B")a: Calculator = Calculator(hp,20B)scala> a ##res58: Int = 1619269961scala> a toStringres59: String = Calculator(hp,20B)scala> a.copy(model = "48G")res60: Calculator = Calculator(hp,48G)scala> val b = Calculator("hp", "20B")b: Calculator = Calculator(hp,20B)
  • case classscala> val a = Calculator("hp", "20B")a: Calculator = Calculator(hp,20B)scala> a ##res58: Int = 1619269961scala> a toStringres59: String = Calculator(hp,20B)scala> a.copy(model = "48G")res60: Calculator = Calculator(hp,48G)scala> val b = Calculator("hp", "20B")b: Calculator = Calculator(hp,20B)scala> a == b
  • case classscala> val a = Calculator("hp", "20B")a: Calculator = Calculator(hp,20B)scala> a ##res58: Int = 1619269961scala> a toStringres59: String = Calculator(hp,20B)scala> a.copy(model = "48G")res60: Calculator = Calculator(hp,48G)scala> val b = Calculator("hp", "20B")b: Calculator = Calculator(hp,20B)scala> a == bres61: Boolean = true
  • Pattern Matching: case class
  • Pattern Matching: case classdef calcType(calc: Calculator) = calc match {
  • Pattern Matching: case classdef calcType(calc: Calculator) = calc match { case Calculator("hp", "20B") => "financial"
  • Pattern Matching: case classdef calcType(calc: Calculator) = calc match { case Calculator("hp", "20B") => "financial" case Calculator("hp", "48G") => "scientific"
  • Pattern Matching: case classdef calcType(calc: Calculator) = calc match { case Calculator("hp", "20B") => "financial" case Calculator("hp", "48G") => "scientific" case Calculator("hp", "30B") => "business"
  • Pattern Matching: case classdef calcType(calc: Calculator) = calc match { case Calculator("hp", "20B") => "financial" case Calculator("hp", "48G") => "scientific" case Calculator("hp", "30B") => "business" case Calculator(b, m) =>
  • Pattern Matching: case classdef calcType(calc: Calculator) = calc match { case Calculator("hp", "20B") => "financial" case Calculator("hp", "48G") => "scientific" case Calculator("hp", "30B") => "business" case Calculator(b, m) => "Calculator: %s %s is of unknown type".format(b, m)
  • Pattern Matching: case classdef calcType(calc: Calculator) = calc match { case Calculator("hp", "20B") => "financial" case Calculator("hp", "48G") => "scientific" case Calculator("hp", "30B") => "business" case Calculator(b, m) => "Calculator: %s %s is of unknown type".format(b, m)}
  • Pattern Matching: case classdef calcType(calc: Calculator) = calc match { case Calculator("hp", "20B") => "financial" case Calculator("hp", "48G") => "scientific" case Calculator("hp", "30B") => "business" case Calculator(b, m) => "Calculator: %s %s is of unknown type".format(b, m)}scala> calcType(Calculator("hp", "20B"))
  • Pattern Matching: case classdef calcType(calc: Calculator) = calc match { case Calculator("hp", "20B") => "financial" case Calculator("hp", "48G") => "scientific" case Calculator("hp", "30B") => "business" case Calculator(b, m) => "Calculator: %s %s is of unknown type".format(b, m)}scala> calcType(Calculator("hp", "20B"))res62: java.lang.String = financial
  • Pattern Matching: case classdef calcType(calc: Calculator) = calc match { case Calculator("hp", "20B") => "financial" case Calculator("hp", "48G") => "scientific" case Calculator("hp", "30B") => "business" case Calculator(b, m) => "Calculator: %s %s is of unknown type".format(b, m)}scala> calcType(Calculator("hp", "20B"))res62: java.lang.String = financialscala> calcType(Calculator("hp", "48G"))
  • Pattern Matching: case classdef calcType(calc: Calculator) = calc match { case Calculator("hp", "20B") => "financial" case Calculator("hp", "48G") => "scientific" case Calculator("hp", "30B") => "business" case Calculator(b, m) => "Calculator: %s %s is of unknown type".format(b, m)}scala> calcType(Calculator("hp", "20B"))res62: java.lang.String = financialscala> calcType(Calculator("hp", "48G"))res63: java.lang.String = scientific
  • Pattern Matching: case classdef calcType(calc: Calculator) = calc match { case Calculator("hp", "20B") => "financial" case Calculator("hp", "48G") => "scientific" case Calculator("hp", "30B") => "business" case Calculator(b, m) => "Calculator: %s %s is of unknown type".format(b, m)}scala> calcType(Calculator("hp", "20B"))res62: java.lang.String = financialscala> calcType(Calculator("hp", "48G"))res63: java.lang.String = scientificscala> calcType(Calculator("kth", "h3"))
  • Pattern Matching: case classdef calcType(calc: Calculator) = calc match { case Calculator("hp", "20B") => "financial" case Calculator("hp", "48G") => "scientific" case Calculator("hp", "30B") => "business" case Calculator(b, m) => "Calculator: %s %s is of unknown type".format(b, m)}scala> calcType(Calculator("hp", "20B"))res62: java.lang.String = financialscala> calcType(Calculator("hp", "48G"))res63: java.lang.String = scientificscala> calcType(Calculator("kth", "h3"))res64: java.lang.String = Calculator: kth h3 is of unknown type
  • Pattern Matching: case class
  • Pattern Matching: case classscala> val calcs = List(Calculator("hp", "20B"),
  • Pattern Matching: case classscala> val calcs = List(Calculator("hp", "20B"), | Calculator("hp", "48G"), Calculator("hp", "30B"),
  • Pattern Matching: case classscala> val calcs = List(Calculator("hp", "20B"), | Calculator("hp", "48G"), Calculator("hp", "30B"), | Calculator("kth", "h3"))
  • Pattern Matching: case classscala> val calcs = List(Calculator("hp", "20B"), | Calculator("hp", "48G"), Calculator("hp", "30B"), | Calculator("kth", "h3"))calcs: List[Calculator] = List(Calculator(hp,20B), Calculator(hp,48G),Calculator(hp,30B), Calculator(kth,h3))
  • Pattern Matching: case classscala> val calcs = List(Calculator("hp", "20B"), | Calculator("hp", "48G"), Calculator("hp", "30B"), | Calculator("kth", "h3"))calcs: List[Calculator] = List(Calculator(hp,20B), Calculator(hp,48G),Calculator(hp,30B), Calculator(kth,h3))scala> calcs.map(calcType).foreach(println)
  • Pattern Matching: case classscala> val calcs = List(Calculator("hp", "20B"), | Calculator("hp", "48G"), Calculator("hp", "30B"), | Calculator("kth", "h3"))calcs: List[Calculator] = List(Calculator(hp,20B), Calculator(hp,48G),Calculator(hp,30B), Calculator(kth,h3))scala> calcs.map(calcType).foreach(println)financial
  • Pattern Matching: case classscala> val calcs = List(Calculator("hp", "20B"), | Calculator("hp", "48G"), Calculator("hp", "30B"), | Calculator("kth", "h3"))calcs: List[Calculator] = List(Calculator(hp,20B), Calculator(hp,48G),Calculator(hp,30B), Calculator(kth,h3))scala> calcs.map(calcType).foreach(println)financialscientific
  • Pattern Matching: case classscala> val calcs = List(Calculator("hp", "20B"), | Calculator("hp", "48G"), Calculator("hp", "30B"), | Calculator("kth", "h3"))calcs: List[Calculator] = List(Calculator(hp,20B), Calculator(hp,48G),Calculator(hp,30B), Calculator(kth,h3))scala> calcs.map(calcType).foreach(println)financialscientificbusiness
  • Pattern Matching: case classscala> val calcs = List(Calculator("hp", "20B"), | Calculator("hp", "48G"), Calculator("hp", "30B"), | Calculator("kth", "h3"))calcs: List[Calculator] = List(Calculator(hp,20B), Calculator(hp,48G),Calculator(hp,30B), Calculator(kth,h3))scala> calcs.map(calcType).foreach(println)financialscientificbusinessCalculator: kth h3 is of unknown type
  • Pattern Matching: case class
  • Pattern Matching: case classExample: Activity Stream
  • Pattern Matching: case class Example: Activity StreamFacebook timeline
  • Pattern Matching: case class Example: Activity StreamFacebook timelineSNS 사용자들의 활동 내역을 추상화
  • Pattern Matching: case class Example: Activity StreamFacebook timelineSNS 사용자들의 활동 내역을 추상화이번 예제에서는 write/like 만 고려
  • Pattern Matching: case class Example: Activity StreamFacebook timelineSNS 사용자들의 활동 내역을 추상화이번 예제에서는 write/like 만 고려
  • Pattern Matching: case class Example: Activity StreamFacebook timelineSNS 사용자들의 활동 내역을 추상화이번 예제에서는 write/like 만 고려 “Someone likes my post”
  • Example: Activity StreamActivity = S(주어) + V(동사) + O(목적어)
  • Example: Activity Stream Activity = S(주어) + V(동사) + O(목적어)case class Activity( sub: Noun, verb: String, obj: Noun)
  • Example: Activity StreamPerson and Post
  • Example: Activity Stream Person and Posttrait Noun
  • Example: Activity Stream Person and Posttrait Nouncase class Person(name: String, age: Int) extends Noun {
  • Example: Activity Stream Person and Posttrait Nouncase class Person(name: String, age: Int) extends Noun { def followers: List[Person] = ...
  • Example: Activity Stream Person and Posttrait Nouncase class Person(name: String, age: Int) extends Noun { def followers: List[Person] = ...}
  • Example: Activity Stream Person and Posttrait Nouncase class Person(name: String, age: Int) extends Noun { def followers: List[Person] = ...}
  • Example: Activity Stream Person and Posttrait Nouncase class Person(name: String, age: Int) extends Noun { def followers: List[Person] = ...}case class Post(author: Person, text: String) extends Noun
  • Example: Activity StreamActivity
  • Example: Activity Stream Activityval jane = Person("Jane", 59)
  • Example: Activity Stream Activityval jane = Person("Jane", 59)val charles = Person("Charles", 50)
  • Example: Activity Stream Activityval jane = Person("Jane", 59)val charles = Person("Charles", 50)val post = Post(jane, "hello, world")
  • Example: Activity Stream Activityval jane = Person("Jane", 59)val charles = Person("Charles", 50)val post = Post(jane, "hello, world")val a1 = Activity(jane, "write", post)
  • Example: Activity Stream Activityval jane = Person("Jane", 59)val charles = Person("Charles", 50)val post = Post(jane, "hello, world")val a1 = Activity(jane, "write", post)val a2 = Activity(charles, "like", post)
  • Example: Activity StreamPush or Email
  • Example: Activity Stream Push or Emaildef sendPush(to: Person, msg: String)
  • Example: Activity Stream Push or Emaildef sendPush(to: Person, msg: String)def sendEmail(to: Person, msg: String)
  • Example: Activity StreamNotification
  • Example: Activity Stream Notificationdef sendNoti(a: Activity) = {
  • Example: Activity Stream Notificationdef sendNoti(a: Activity) = { a match {
  • Example: Activity Stream Notificationdef sendNoti(a: Activity) = { a match { case Activity(someone: Person, "like", Post(author, _)) =>
  • Example: Activity Stream Notificationdef sendNoti(a: Activity) = { a match { case Activity(someone: Person, "like", Post(author, _)) => sendPush(
  • Example: Activity Stream Notificationdef sendNoti(a: Activity) = { a match { case Activity(someone: Person, "like", Post(author, _)) => sendPush( author,
  • Example: Activity Stream Notificationdef sendNoti(a: Activity) = { a match { case Activity(someone: Person, "like", Post(author, _)) => sendPush( author, "%s likes your post".format(someone.name))
  • Example: Activity Stream Notificationdef sendNoti(a: Activity) = { a match { case Activity(someone: Person, "like", Post(author, _)) => sendPush( author, "%s likes your post".format(someone.name)) case Activity(someone: Person, "write", _) =>
  • Example: Activity Stream Notificationdef sendNoti(a: Activity) = { a match { case Activity(someone: Person, "like", Post(author, _)) => sendPush( author, "%s likes your post".format(someone.name)) case Activity(someone: Person, "write", _) => someone.followers.foreach(
  • Example: Activity Stream Notificationdef sendNoti(a: Activity) = { a match { case Activity(someone: Person, "like", Post(author, _)) => sendPush( author, "%s likes your post".format(someone.name)) case Activity(someone: Person, "write", _) => someone.followers.foreach( p =>
  • Example: Activity Stream Notificationdef sendNoti(a: Activity) = { a match { case Activity(someone: Person, "like", Post(author, _)) => sendPush( author, "%s likes your post".format(someone.name)) case Activity(someone: Person, "write", _) => someone.followers.foreach( p => sendEmail(
  • Example: Activity Stream Notificationdef sendNoti(a: Activity) = { a match { case Activity(someone: Person, "like", Post(author, _)) => sendPush( author, "%s likes your post".format(someone.name)) case Activity(someone: Person, "write", _) => someone.followers.foreach( p => sendEmail( p, "%s write new post".format(someone.name)))
  • Example: Activity Stream Notificationdef sendNoti(a: Activity) = { a match { case Activity(someone: Person, "like", Post(author, _)) => sendPush( author, "%s likes your post".format(someone.name)) case Activity(someone: Person, "write", _) => someone.followers.foreach( p => sendEmail( p, "%s write new post".format(someone.name))) }
  • Example: Activity Stream Notificationdef sendNoti(a: Activity) = { a match { case Activity(someone: Person, "like", Post(author, _)) => sendPush( author, "%s likes your post".format(someone.name)) case Activity(someone: Person, "write", _) => someone.followers.foreach( p => sendEmail( p, "%s write new post".format(someone.name))) }}
  • 조금 더 우아하게!
  • 좀 더 우아하게 !object Activities { trait Activity trait Noun case class write(sub: Noun, obj: Noun) extends Activity case class like(sub: Noun, obj: Noun) extends Activity case class Sub(n: Noun) { def like(obj: Noun) = Activities.like(n, obj) def write(obj: Noun) = Activities.write(n, obj) } implicit def nounToSub(n: Noun) = Sub(n) case class Person(name: String, age: Int) extends Noun { def followers: List[Person] = Nil } case class Post(author: Person, text: String) extends Noun}
  • 좀 더 우아하게!
  • 좀 더 우아하게!val jane = Person("Jane", 59)
  • 좀 더 우아하게!val jane = Person("Jane", 59)val charles = Person("Charles", 50)
  • 좀 더 우아하게!val jane = Person("Jane", 59)val charles = Person("Charles", 50)val post = Post(jane, "hello, world")
  • 좀 더 우아하게!val jane = Person("Jane", 59)val charles = Person("Charles", 50)val post = Post(jane, "hello, world")val a1 = jane write post
  • 좀 더 우아하게!val jane = Person("Jane", 59)val charles = Person("Charles", 50)val post = Post(jane, "hello, world")val a1 = jane write postval a2 = charles like post
  • 좀 더 우아하게!val jane = Person("Jane", 59)val charles = Person("Charles", 50)val post = Post(jane, "hello, world")val a1 = jane write postval a2 = charles like postdef sendNoti(a: Activity) {
  • 좀 더 우아하게!val jane = Person("Jane", 59)val charles = Person("Charles", 50)val post = Post(jane, "hello, world")val a1 = jane write postval a2 = charles like postdef sendNoti(a: Activity) { a match {
  • 좀 더 우아하게!val jane = Person("Jane", 59)val charles = Person("Charles", 50)val post = Post(jane, "hello, world")val a1 = jane write postval a2 = charles like postdef sendNoti(a: Activity) { a match { case someone write post => ...
  • 좀 더 우아하게!val jane = Person("Jane", 59)val charles = Person("Charles", 50)val post = Post(jane, "hello, world")val a1 = jane write postval a2 = charles like postdef sendNoti(a: Activity) { a match { case someone write post => ... case Person(name, age) like Post(author, text) => ...
  • 좀 더 우아하게!val jane = Person("Jane", 59)val charles = Person("Charles", 50)val post = Post(jane, "hello, world")val a1 = jane write postval a2 = charles like postdef sendNoti(a: Activity) { a match { case someone write post => ... case Person(name, age) like Post(author, text) => ... }
  • 좀 더 우아하게!val jane = Person("Jane", 59)val charles = Person("Charles", 50)val post = Post(jane, "hello, world")val a1 = jane write postval a2 = charles like postdef sendNoti(a: Activity) { a match { case someone write post => ... case Person(name, age) like Post(author, text) => ... }}
  • Pattern Matching
  • Pattern MatchingMore usage
  • Pattern Matching More usageval Person(name, age) = Person(“tao”,35)
  • Pattern Matching More usageval Person(name, age) = Person(“tao”,35)“for” expression
  • Pattern Matching More usageval Person(name, age) = Person(“tao”,35)“for” expressionCollections
  • Pattern Matching More usageval Person(name, age) = Person(“tao”,35)“for” expressionCollectionsExtractors
  • Pattern Matching More usageval Person(name, age) = Person(“tao”,35)“for” expressionCollectionsExtractorsXML
  • Horizontal Scale
  • Horizontal Scale The Multi-core Era✓ Moore Law => 반도체 집적 회로의 성능은 18개월 마다 2배로 증간한다 => 최근에는 클럭수가 아닌 코어의 증가로 이루어짐 The Big-data Era✓ 마구 쏟아지는 엄청난 데이터를 처리해야함 병렬/동시/분산 처리가 중요해짐✓ 하지만, 동시성 문제는 언제나 어렵다
  • 왜?
  • Horizontal Scale Root Cause 공유된 변경 가능한 상태 shared mutable state 동기화 synchronization✓ monitor & lock 예측 불가능한 상황을 피하기 위해서는✓ 변경 가능한 상태 mutable state 를 만들지 말아야 함✓ 즉, functional style 로 코드를 작성해야함
  • “ 프로그램들은 버그로 가득차Thread를 사용하는 대부분의 있다 - Havoc Pennington @ Dreamforce 2011 ”
  • Thread-lessconcurrencyActor model
  • Actor model
  • Actor modelActor Model
  • Actor model Actor Model동시성 문제를 위한 더 단순한 고수준의 추상화 모델
  • Actor model Actor Model 동시성 문제를 위한 더 단순한 고수준의 추상화 모델✓ Actors are objects which encapsulate state and behavior
  • Actor model Actor Model 동시성 문제를 위한 더 단순한 고수준의 추상화 모델✓ Actors are objects which encapsulate state and behavior Erlang 이라는 언어를 통해 널리 알려짐
  • Actor model Actor Model 동시성 문제를 위한 더 단순한 고수준의 추상화 모델✓ Actors are objects which encapsulate state and behavior Erlang 이라는 언어를 통해 널리 알려짐 Message passing, no shared memory
  • Actor model Actor Model 동시성 문제를 위한 더 단순한 고수준의 추상화 모델✓ Actors are objects which encapsulate state and behavior Erlang 이라는 언어를 통해 널리 알려짐 Message passing, no shared memory Event loop
  • Worker vs Actor WorkerQueue Worker take lock Shared Job Memory Worker #3 put Worker
  • Worker vs Actor Actor #1 mailbox messagemessages Actor #2 To: Actor#1 Actor #3 Actor #4
  • Scala Actor
  • “ Bruce: “그 때(루비를 만들었을 당시)로 돌아간다 면, 어떤 기능에 변화를 주고 싶으세요?” Matz: “Thread를 없애고, Actor 나 또는 좀 더 진 보된 형태의 동시성 기능을 추가했을거에요” Interview with Yukihiro Matsumoto (the creator of Ruby) from the book, “Seven Languages in Seven Weeks” ”
  • Scala Actor
  • Scala ActorAkka
  • Scala Actor AkkaScala로 작성된 Actor model 구현
  • Scala Actor AkkaScala로 작성된 Actor model 구현TypeSafe Stack with Play! Framework
  • Scala Actor AkkaScala로 작성된 Actor model 구현TypeSafe Stack with Play! Framework곧 Scala에 built-in 될 예정
  • Scala Actor Akka Scala로 작성된 Actor model 구현 TypeSafe Stack with Play! Framework 곧 Scala에 built-in 될 예정✓ 기존 Scala 자체 구현은 deprecate 될 예정
  • Scala Actor Akka Scala로 작성된 Actor model 구현 TypeSafe Stack with Play! Framework 곧 Scala에 built-in 될 예정✓ 기존 Scala 자체 구현은 deprecate 될 예정 자바를 위한 별도 API 제공
  • Scala Actor Akka Scala로 작성된 Actor model 구현 TypeSafe Stack with Play! Framework 곧 Scala에 built-in 될 예정✓ 기존 Scala 자체 구현은 deprecate 될 예정 자바를 위한 별도 API 제공 Asynchronous/non-blocking
  • Scala Actor Akka Scala로 작성된 Actor model 구현 TypeSafe Stack with Play! Framework 곧 Scala에 built-in 될 예정✓ 기존 Scala 자체 구현은 deprecate 될 예정 자바를 위한 별도 API 제공 Asynchronous/non-blocking 격리된 변경 가능 상태 Isolated mutable state
  • Akka Actorimport akka.actor.Actorimport akka.actor.Propsimport akka.event.Loggingclass MyActor extends Actor { val log = Logging(context.system, this) def receive = { case "test" log.info("received test") case _ log.info("received unknown message") }}
  • Akka Actorimport akka.actor.Actorimport akka.actor.Propsimport akka.event.Loggingclass MyActor extends Actor { val log = Logging(context.system, this) def receive = { case "test" log.info("received test") case _ log.info("received unknown message") }}
  • Akka
  • AkkaCreating actor
  • Akka Creating actorval system = ActorSystem("MySystem")val myActor = system.actorOf(Props[MyActor], name = "myactor")
  • Akka Creating actorval system = ActorSystem("MySystem")val myActor = system.actorOf(Props[MyActor], name = "myactor") Sending a message
  • Akka Creating actorval system = ActorSystem("MySystem")val myActor = system.actorOf(Props[MyActor], name = "myactor") Sending a messagemyActor ! "test"myActor.tell("test")
  • Akka Creating actorval system = ActorSystem("MySystem")val myActor = system.actorOf(Props[MyActor], name = "myactor") Sending a messagemyActor ! "test"myActor.tell("test") Tell: Fire and Forget
  • Akka
  • AkkaReplying
  • Akka Replyingdef receive = { case "ping" sender ! "pong" ...
  • Akka Replyingdef receive = { case "ping" sender ! "pong" ... Asking
  • Akka Replyingdef receive = { case "ping" sender ! "pong" ... Askingval future1 = pingpongActor ? "ping"val future2 = pingpongActor.ask("ping")
  • Example: ActivityStream
  • Example: ActivityStreamclass NotiActor extends Actor {
  • Example: ActivityStreamclass NotiActor extends Actor { def sendPush(to: Person, msg: String) {
  • Example: ActivityStreamclass NotiActor extends Actor { def sendPush(to: Person, msg: String) { println("Send Push [To: %s][Msg: %s]".format(to, msg))
  • Example: ActivityStreamclass NotiActor extends Actor { def sendPush(to: Person, msg: String) { println("Send Push [To: %s][Msg: %s]".format(to, msg)) }
  • Example: ActivityStreamclass NotiActor extends Actor { def sendPush(to: Person, msg: String) { println("Send Push [To: %s][Msg: %s]".format(to, msg)) } def sendEmail(to: Person, msg: String) {
  • Example: ActivityStreamclass NotiActor extends Actor { def sendPush(to: Person, msg: String) { println("Send Push [To: %s][Msg: %s]".format(to, msg)) } def sendEmail(to: Person, msg: String) { println("Send Email [To: %s][Msg: %s]".format(to, msg))
  • Example: ActivityStreamclass NotiActor extends Actor { def sendPush(to: Person, msg: String) { println("Send Push [To: %s][Msg: %s]".format(to, msg)) } def sendEmail(to: Person, msg: String) { println("Send Email [To: %s][Msg: %s]".format(to, msg)) }
  • Example: ActivityStreamclass NotiActor extends Actor { def sendPush(to: Person, msg: String) { println("Send Push [To: %s][Msg: %s]".format(to, msg)) } def sendEmail(to: Person, msg: String) { println("Send Email [To: %s][Msg: %s]".format(to, msg)) } def receive = {
  • Example: ActivityStreamclass NotiActor extends Actor { def sendPush(to: Person, msg: String) { println("Send Push [To: %s][Msg: %s]".format(to, msg)) } def sendEmail(to: Person, msg: String) { println("Send Email [To: %s][Msg: %s]".format(to, msg)) } def receive = { case Person(name, _) like Post(author, _) =>
  • Example: ActivityStreamclass NotiActor extends Actor { def sendPush(to: Person, msg: String) { println("Send Push [To: %s][Msg: %s]".format(to, msg)) } def sendEmail(to: Person, msg: String) { println("Send Email [To: %s][Msg: %s]".format(to, msg)) } def receive = { case Person(name, _) like Post(author, _) => sendPush(author, "%s likes your post".format(name))
  • Example: ActivityStreamclass NotiActor extends Actor { def sendPush(to: Person, msg: String) { println("Send Push [To: %s][Msg: %s]".format(to, msg)) } def sendEmail(to: Person, msg: String) { println("Send Email [To: %s][Msg: %s]".format(to, msg)) } def receive = { case Person(name, _) like Post(author, _) => sendPush(author, "%s likes your post".format(name)) case (someone@Person(name, _)) write _ =>
  • Example: ActivityStreamclass NotiActor extends Actor { def sendPush(to: Person, msg: String) { println("Send Push [To: %s][Msg: %s]".format(to, msg)) } def sendEmail(to: Person, msg: String) { println("Send Email [To: %s][Msg: %s]".format(to, msg)) } def receive = { case Person(name, _) like Post(author, _) => sendPush(author, "%s likes your post".format(name)) case (someone@Person(name, _)) write _ => someone.followers.foreach{
  • Example: ActivityStreamclass NotiActor extends Actor { def sendPush(to: Person, msg: String) { println("Send Push [To: %s][Msg: %s]".format(to, msg)) } def sendEmail(to: Person, msg: String) { println("Send Email [To: %s][Msg: %s]".format(to, msg)) } def receive = { case Person(name, _) like Post(author, _) => sendPush(author, "%s likes your post".format(name)) case (someone@Person(name, _)) write _ => someone.followers.foreach{ p =>
  • Example: ActivityStreamclass NotiActor extends Actor { def sendPush(to: Person, msg: String) { println("Send Push [To: %s][Msg: %s]".format(to, msg)) } def sendEmail(to: Person, msg: String) { println("Send Email [To: %s][Msg: %s]".format(to, msg)) } def receive = { case Person(name, _) like Post(author, _) => sendPush(author, "%s likes your post".format(name)) case (someone@Person(name, _)) write _ => someone.followers.foreach{ p => sendEmail(p,
  • Example: ActivityStreamclass NotiActor extends Actor { def sendPush(to: Person, msg: String) { println("Send Push [To: %s][Msg: %s]".format(to, msg)) } def sendEmail(to: Person, msg: String) { println("Send Email [To: %s][Msg: %s]".format(to, msg)) } def receive = { case Person(name, _) like Post(author, _) => sendPush(author, "%s likes your post".format(name)) case (someone@Person(name, _)) write _ => someone.followers.foreach{ p => sendEmail(p, "Your friend(%s) write new post".format(name))
  • Example: ActivityStreamclass NotiActor extends Actor { def sendPush(to: Person, msg: String) { println("Send Push [To: %s][Msg: %s]".format(to, msg)) } def sendEmail(to: Person, msg: String) { println("Send Email [To: %s][Msg: %s]".format(to, msg)) } def receive = { case Person(name, _) like Post(author, _) => sendPush(author, "%s likes your post".format(name)) case (someone@Person(name, _)) write _ => someone.followers.foreach{ p => sendEmail(p, "Your friend(%s) write new post".format(name)) }
  • Example: ActivityStreamclass NotiActor extends Actor { def sendPush(to: Person, msg: String) { println("Send Push [To: %s][Msg: %s]".format(to, msg)) } def sendEmail(to: Person, msg: String) { println("Send Email [To: %s][Msg: %s]".format(to, msg)) } def receive = { case Person(name, _) like Post(author, _) => sendPush(author, "%s likes your post".format(name)) case (someone@Person(name, _)) write _ => someone.followers.foreach{ p => sendEmail(p, "Your friend(%s) write new post".format(name)) } }
  • Example: ActivityStreamclass NotiActor extends Actor { def sendPush(to: Person, msg: String) { println("Send Push [To: %s][Msg: %s]".format(to, msg)) } def sendEmail(to: Person, msg: String) { println("Send Email [To: %s][Msg: %s]".format(to, msg)) } def receive = { case Person(name, _) like Post(author, _) => sendPush(author, "%s likes your post".format(name)) case (someone@Person(name, _)) write _ => someone.followers.foreach{ p => sendEmail(p, "Your friend(%s) write new post".format(name)) } }}
  • Example: ActivityStreamSending activities
  • Example: ActivityStream Sending activitiesval jane = Person("Jane", 59)
  • Example: ActivityStream Sending activitiesval jane = Person("Jane", 59)val charles = Person("Charles", 50)
  • Example: ActivityStream Sending activitiesval jane = Person("Jane", 59)val charles = Person("Charles", 50)val post = Post(jane, "hello, world")
  • Example: ActivityStream Sending activitiesval jane = Person("Jane", 59)val charles = Person("Charles", 50)val post = Post(jane, "hello, world")val system = ActorSystem("ActivityStream")
  • Example: ActivityStream Sending activitiesval jane = Person("Jane", 59)val charles = Person("Charles", 50)val post = Post(jane, "hello, world")val system = ActorSystem("ActivityStream")val notiActor = system.actorOf(
  • Example: ActivityStream Sending activitiesval jane = Person("Jane", 59)val charles = Person("Charles", 50)val post = Post(jane, "hello, world")val system = ActorSystem("ActivityStream")val notiActor = system.actorOf( Props[NotiActor], "notification")
  • Example: ActivityStream Sending activitiesval jane = Person("Jane", 59)val charles = Person("Charles", 50)val post = Post(jane, "hello, world")val system = ActorSystem("ActivityStream")val notiActor = system.actorOf( Props[NotiActor], "notification")notiActor ! (jane write post)
  • Example: ActivityStream Sending activitiesval jane = Person("Jane", 59)val charles = Person("Charles", 50)val post = Post(jane, "hello, world")val system = ActorSystem("ActivityStream")val notiActor = system.actorOf( Props[NotiActor], "notification")notiActor ! (jane write post)notiActor ! (charles like post)
  • Example: ActivityStreamScale Up (Concurrency)
  • Example: ActivityStream Scale Up (Concurrency)val notiActor = system.actorOf( Props[NotiActor].withRouter(RoundRobinRouter(5)) "notication")
  • Example: ActivityStream Scale Up (Concurrency)val notiActor = system.actorOf( Props[NotiActor].withRouter(RoundRobinRouter(5)) "notication")val notiActor = system.actorOf( Props[NotiActor].withRouter(SmallestMailboxRouter(5)) "notication")
  • Example: ActivityStreamScale Out (Remoting)
  • Example: ActivityStream Scale Out (Remoting)val notiActor = context.actorFor( "akka://activity@192.168.10.2:2552/user/notification")
  • Example: ActivityStream Scale Out (Remoting)val notiActor = context.actorFor( "akka://activity@192.168.10.2:2552/user/notification")val notiActor = context.actorFor( "cluster://acitivties/notification")
  • Example: ActivityStream Scale Out (Remoting)val notiActor = context.actorFor( "akka://activity@192.168.10.2:2552/user/notification")val notiActor = context.actorFor( "cluster://acitivties/notification") Location Transparency coming soon !
  • Example: ActivityStream Scale Out (Remoting)val notiActor = context.actorFor( "akka://activity@192.168.10.2:2552/user/notification")val notiActor = context.actorFor( "cluster://acitivties/notification") ? Location Transparency coming soon !
  • Akka More UsageEvent BusSchedulerFault ToleranceSTM (Software Transactional Memory)FSM (Finite State Machine)Asynchronous IOExtensions for ZeroMQ, Camel, ...
  • Scala?
  • 더 강력한 표현력더 강력한 동시성 처리기존 JVM 기반 환경 재사 용
  • 다른 언어는같은 문제를다른 방법으로해결합니다
  • 참고문헌과 더 읽을 거리들 Programming in Scala, 2nd edition✓ http://www.artima.com/shop/programming_in_scala_2ed http://www.scala-lang.org/ http://doc.akka.io/docs/akka/2.0.3/ http://en.wikipedia.org/wiki/Scala http://en.wikipedia.org/wiki/Functional_programming http://en.wikipedia.org/wiki/Actor_model http://twitter.github.com/scala_school/ 꽃보다 Scala(long version)✓ https://docs.google.com/document/pub? id=1kSNKKKwM8rjGhn9Gnw-6Q0VCImpwSRZ7_QzwNwXgMxM http://blog.typesafe.com/scala-on-heroku Seven Languages in Seven Weeks✓ http://www.amazon.co.uk/Seven-Languages-Weeks-Programming-Programmers/dp/193435659X
  • 참고문헌과 더 읽을 거리들 Functional ProgrammingPrinciples in Scala https://www.coursera.org/ course/progfun by Martin Odersky, the creator of Scala
  • Q&A