[함수형 사고] 책을 읽고 진행한 PT
Java 8, Scala, Clojure, Groovy 등의 함수형 프로그래밍 언어에서 사용하고 있는 패러다임을 익힐 수 있습니다.
책을 요약하고 PT를 진행하려고 하니 미숙한 부분이 많으니, 자세한 부분은 책을 참고 부탁드립니다.
책에서는 주로 Groovy에 대한 코드가 많았는데, Scala에 조금 더 익숙하기 때문에 Scala로 작성한 코드가 많습니다.
"R을 이용한 데이터 처리 & 분석 실무 - 서민구 지음" 정리 자료 #4
- https://thebook.io/006723/
- 첫번째 : goo.gl/FJjOlq
- 두번째 : goo.gl/Wdb90g
- 세번째 : goo.gl/80VGcn
- 네번째 : goo.gl/lblUsR
"R을 이용한 데이터 처리 & 분석 실무 - 서민구 지음" 정리 자료 #2
- https://thebook.io/006723/
- 첫번째 : goo.gl/FJjOlq
- 두번째 : goo.gl/Wdb90g
- 세번째 : goo.gl/80VGcn
- 네번째 : goo.gl/lblUsR
"R을 이용한 데이터 처리 & 분석 실무 - 서민구 지음" 정리 자료 #1
- https://thebook.io/006723/
- 첫번째 : goo.gl/FJjOlq
- 두번째 : goo.gl/Wdb90g
- 세번째 : goo.gl/80VGcn
- 네번째 : goo.gl/lblUsR
"R을 이용한 데이터 처리 & 분석 실무 - 서민구 지음" 정리 자료 #4
- https://thebook.io/006723/
- 첫번째 : goo.gl/FJjOlq
- 두번째 : goo.gl/Wdb90g
- 세번째 : goo.gl/80VGcn
- 네번째 : goo.gl/lblUsR
"R을 이용한 데이터 처리 & 분석 실무 - 서민구 지음" 정리 자료 #2
- https://thebook.io/006723/
- 첫번째 : goo.gl/FJjOlq
- 두번째 : goo.gl/Wdb90g
- 세번째 : goo.gl/80VGcn
- 네번째 : goo.gl/lblUsR
"R을 이용한 데이터 처리 & 분석 실무 - 서민구 지음" 정리 자료 #1
- https://thebook.io/006723/
- 첫번째 : goo.gl/FJjOlq
- 두번째 : goo.gl/Wdb90g
- 세번째 : goo.gl/80VGcn
- 네번째 : goo.gl/lblUsR
"R을 이용한 데이터 처리 & 분석 실무 - 서민구 지음" 정리 자료 #3
- https://thebook.io/006723/
- 첫번째 : goo.gl/FJjOlq
- 두번째 : goo.gl/Wdb90g
- 세번째 : goo.gl/80VGcn
- 네번째 : goo.gl/lblUsR
2D 컴퓨터비젼에 대한 설명. 영상으로부터 정보를 추출해내는 공학/과학 분과인 컴퓨터비젼의 기술에 대한 쉬운 설명. 파이썬(Python)의 컴퓨터비젼/영상처리 라이브러리인 scikit-image를 주로 활용하였으며 코드를 함께 담음.
R컨퍼런스 발표본 (2014.5.30) 임.
이 자료는 이영록강사님이 2011년 iOS 개발자 포럼에서 발표한 내용을 약간 개선하고 정리한 자료입니다.
iOS의 메모리관리 기법은 retain count라고 하는 독특하면서도 효율적인 방법을 사용하며 최근에 발표된 Xcode에서는 Automatic Reference Counting(ARC) 기법을 통해 release를 사용하에 객체를 소거하는 불편함을 많이 개선하였습니다.
본 자료에서는 이러한 점에 대한 비교적 상세한 설명을 담고 있습니다.
"R을 이용한 데이터 처리 & 분석 실무 - 서민구 지음" 정리 자료 #3
- https://thebook.io/006723/
- 첫번째 : goo.gl/FJjOlq
- 두번째 : goo.gl/Wdb90g
- 세번째 : goo.gl/80VGcn
- 네번째 : goo.gl/lblUsR
2D 컴퓨터비젼에 대한 설명. 영상으로부터 정보를 추출해내는 공학/과학 분과인 컴퓨터비젼의 기술에 대한 쉬운 설명. 파이썬(Python)의 컴퓨터비젼/영상처리 라이브러리인 scikit-image를 주로 활용하였으며 코드를 함께 담음.
R컨퍼런스 발표본 (2014.5.30) 임.
이 자료는 이영록강사님이 2011년 iOS 개발자 포럼에서 발표한 내용을 약간 개선하고 정리한 자료입니다.
iOS의 메모리관리 기법은 retain count라고 하는 독특하면서도 효율적인 방법을 사용하며 최근에 발표된 Xcode에서는 Automatic Reference Counting(ARC) 기법을 통해 release를 사용하에 객체를 소거하는 불편함을 많이 개선하였습니다.
본 자료에서는 이러한 점에 대한 비교적 상세한 설명을 담고 있습니다.
[Main Session] 미래의 Java 미리보기 - 앰버와 발할라 프로젝트를 중심으로Oracle Korea
OpenJDK로 Java 언어 개선 주도권이 넘어간 후 Java의 개선 속도가 몰라보게 빨라지고 있습니다. Java를 언어, 런타임, 표준 API로 나눌 때 프로그래머에게 가장 중요하다고 볼 수 있는 언어 관점에서 Java가 앞으로 어떻게 개선될 지, Java의 미래를 알아보려고 합니다.
4. 문제 1
가장 많이 사용된 회사 이름들을 찾고, 그 이
름들의 빈도를 정렬된 목록으로 출력
(Samsung, LG 제외)
Samsung LG, Google, Apple Microsoft, Facebook, GE Disney , IBM, Toyota,
Starbucks, Samsung LG, Google, Apple Microsoft, Facebook, GE Disney ,
IBM, Toyota, Starbucks, Samsung LG, Apple Microsoft, Facebook, GE
Disney , IBM, Toyota, Starbucks, Samsung LG, Google, Apple Microsoft,
Facebook, Starbucks, Apple, Twitter, Kakao, Kakao Samsung LG, Google,
Apple Microsoft, Facebook, GE Disney , IBM, Toyota, Starbucks, Samsung
LG, Google, Apple Microsoft, Facebook, GE Disney , IBM Starbucks, Apple,
Twitter, Kakao, Kakao Samsung LG, Google, Apple Microsoft, Facebook,
GE Disney , IBM, Toyota, Starbucks, Samsung LG …
5. 문제 1
- 공백 구분
- 쉼표 구분
Samsung LG, Google, Apple Microsoft, Facebook, GE Disney , IBM, Toyota,
Starbucks, Samsung LG, Google, Apple Microsoft, Facebook, GE Disney ,
IBM, Toyota, Starbucks, Samsung LG, Apple Microsoft, Facebook, GE
Disney , IBM, Toyota, Starbucks, Samsung LG, Google, Apple Microsoft,
Facebook, Starbucks, Apple, Twitter, Kakao, Kakao Samsung LG, Google,
Apple Microsoft, Facebook, GE Disney , IBM, Toyota, Starbucks, Samsung
LG, Google, Apple Microsoft, Facebook, GE Disney , IBM Starbucks, Apple,
Twitter, Kakao, Kakao Samsung LG, Google, Apple Microsoft, Facebook,
GE Disney , IBM, Toyota, Starbucks, Samsung LG …
6. Java 7
final private Set<String> EXCLUSION = new HashSet<String>(){{
add("samsung"); add("lg");
}};
public Map companyFreqJava7(String companies){
TreeMap<String, Integer> companyMap = new TreeMap<>();
Matcher m = Pattern.compile("w+").matcher(companies);
while(m.find()){
String company = m.group().toLowerCase();
if(!EXCLUSION.contains(company)){
if(companyMap.get(company) == null){
companyMap.put(company, 1);
}
else{
companyMap.put(company, companyMap.get(company) + 1);
}
}
}
return companyMap;
}
7. Java 8
final private Set<String> EXCLUSION = new HashSet<String>(){{
add("samsung"); add("lg");
}};
private List<String> regexToList(String companies, String regex){
List companyList = new ArrayList<>();
Matcher m = Pattern.compile(regex).matcher(companies);
while(m.find())
companyList.add(m.group());
return companyList;
}
public Map companyFreqJava8(String companies){
TreeMap<String, Integer> companyMap = new TreeMap<>();
regexToList(companies, "w+")
.stream()
.map(w -> w.toLowerCase())
.filter(w -> !EXCLUSION.contains(w))
.forEach(w -> companyMap.put(w, companyMap.getOrDefault(w,0) + 1));
return companyMap;
}
8. 기존 OOP
• 움직이는 부분(mutable)을 캡슐화하여 코드 이해를 도움
• 캡슐화, 스코핑, 가시성 등의 메커니즘
• 상태(state) 변화를 위한 세밀한 제어
• Class마다 고유한 자료구조 - GOF 디자인 패턴
• 쓰레드까지 고려하면 어휴…
9. 함수형 프로그래밍
• 움직이는 부분을 제거(Immutable)
• 최적화된 몇몇 자료구조만 사용(list, set, map)
• 자료구조 + 고계함수 (고 수준의 추상화)
• 고계함수(higher-order function)
– 아래 두 가지 사항 중, 적어도 하나 만족
– 하나 이상의 함수를 매개변수로 취함
– 함수의 결과를 함수로 반환
regexToList(companies, "w+").stream()
.filter(w -> !EXCLUSION.contains(w))
11. 문제 2
회사 이름 목록에서 한 글자로 된 이름을 제
외한 모든 이름을 첫 글자만 대문자화해서 쉼
표로 연결한 문자열을 출력
samsung, lg, Google,a,b,c,d, apple, microsoft, facebook, gE, Disney , ibm,
Toyota, starbucks,x,y,z
Samsung, Lg, Google,a,b,c,d Apple, Microsoft, Facebook, GE, Disney , Ibm,
Toyota, Starbucks,x,y,z
20. 클로저 (Closure)
case class Product(name:String, price:Int) // Scala example
def paidMore(amount: Int) = {(p:Product) => p.price > amount}
def isHighPaid = paidMore(500)
case class Product(name:String, price:Int)
def isHighPaid(p:Product) = p.price > 500
21. case class Product(name:String, price:Int) // Scala example
def paidMore(amount: Int) = {(p:Product) => p.price > amount}
def isHighPaid = paidMore(500)
val tv = Product("TV",1000)
val phone = Product("Phone",100)
println (isHighPaid(tv))
println (isHighPaid(phone))
//true, false
클로저 (Closure)
22. 클로저 (Closure)
case class Product(name:String, price:Int) // Scala example
def paidMore(amount: Int) = {(p:Product) => p.price > amount}
def isHighPaid = paidMore(10)
• 다른 amount를 이용해 새 함수 생성
val tv = Product("TV",1000)
val phone = Product("Phone",100)
println (isHighPaid(tv))
println (isHighPaid(phone))
//true, true
23. 클로저 (Closure)
• enclosing context : 문맥을 포괄함
• 내부에서 참조되는 모든 인수에 대한 묵시적 바인딩
val makeCounter = {
var local:Int = 0
() => {
local += 1
//return local
local
}
}
// Scala example
def func1 = makeCounter()
func1
func1
func1
def func2 = makeCounter()
println(s"func1 : ${func1}");
println(s"func2 : ${func2}");
//func1 : 4
//func2 : 2
24. 커링과 부분 적용
• 수학자 해스켈 커리(Haskell Brooks Curry) 등에서 유
래
• 함수나 메서드의 인수(parameter)의 개수를 조작
25. 커링과 부분 적용
• 커링(Currying)
– 다 인수 함수를 일 인수 함수들의 체인으로 바꾸는
func(a,b,c) -> func(a)(b)(c),func(a), func(a)(b)
• 부분 적용 (Partial application)
– 다 인수 함수의 생략될 인수의 값을 미리 정해서 더 적은 수
의 인수를 받는 하나의 함수로 변경
func(a,b,c) -> func(a,b)
27. 부분 적용(Partial application)
def price(product:String) : Int =
product match {
case "TV" => 1000
case "Phone" => 100
}
def withTax(cost:Int, state: String) : Int
=
state match {
case "NY" => cost * 2
case "FL" => cost * 3
case "OR" => 0
}
// Scala example
val NYTaxed = withTax(_:Int, "NY")
val ORTaxed = withTax(_:Int, "OR")
val NYcostOfPhone =
NYTaxed(price("Phone"))
val ORcostOfTV =
ORTaxed(price("TV"))
println(NYcostOfPhone)
println(ORcostOfTV)
//200
//0
28. 재귀
• 꼬리 호출 최적화(tail-call optimization)
• 재귀 호출이 함수에서 마지막 단계이면, 런타임이 스
택을 증가시키지 않고 스택에 놓여 있는 결과를 교체
• 스택 오버플로우를 우회
def filter(xs: List[Int], p: Int => Boolean): List[Int] =
if (xs.isEmpty) xs
else if (p(xs.head)) xs.head :: filter(xs.tail, p)
else filter(xs.tail, p)
31. 메모이제이션(memoization)
• 캐싱 방법이 제대로 작동하려면? => 순수 함수
• 순수 함수
– 부수 효과가 없는 함수
– 불변 클래스 필드를 참고하지 않음
– 리턴 값 외에는 아무 값도 쓰지 않음
– 주어진 매개 변수에만 의존
– ex) java.lang.Math
32. 문제 3
- 계단 오르기
당신은 계단을 오르고 있습니다.
꼭대기까지 오르기 위해 N개의 계단을 올라가야 합니다.
매번 1 or 2개의 계단을 올라갈 수 있습니다.
계단을 올라가는 방법이 몇 개가 있을까요?
N : 양의 정수
https://leetcode.com/problems/climbing-stairs/#/description
39. 문제 3
- 계단 오르기 groovy
- @Memoizeed 제공
import groovy.transform.Memoized
@Memoized
int memoizedClimb(n){
if(n == 0 || n == 1)
return 1
return memoizedClimb(n-2) + memoizedClimb(n-1)
}
memoizedClimb(5)
40. 문제 3
- 계단 오르기 clojure
- memoize() 제공
(defn climb [n]
(case n
0 1
1 1
(+ (climb (- n 1))
(climb (- n 2)))))
(def cachedClimb (memoize climb))
(println (cachedClimb 5))
41. 문제 3
- 계단 오르기 scala
- getOrElseUpdate()를 이용해 구현
def memoize[A, B](func: A => B) = new (A => B) {
val cache = scala.collection.mutable.Map[A, B]()
def apply(x: A): B = cache.getOrElseUpdate(x, func(x))
}
def memoizedClimb = memoize(climb)
memoizedClimb(5)
42. 게으름(Lazy evaluation)
• 시간이 많이 걸리는 연산을 반드시 필요할 때까지 미
룸
• 요청이 계속되는 한 요소를 계속 전달하는 무한 컬렉
션을 만들 수 있음
• 맵이나 필터 같은 함수형 개념을 게으르게 사용하면,
효율이 높은 코드를 만들 수 있음
45. 문제를 향하여 언어를 구부리기
• Java는 언어로써 유연하지 못하기 때문에, 아이디어
를 기존의 고정된 구조에 맞게 주물러야 함
• Scala는 내부 DSL(Domain Specific Language)을 지
원하기 위해 설계된 언어
• Clojure와 같은 모든 Lisp 계열 언어들도 문제에 맞게
언어를 바꾸는 유연성이 좋음
46. 문제를 향하여 언어를 구부리기
• Scala : Xpath 쿼리를 언어 자체에서 지원
• Xpath : XML Path Language
• https://ko.wikipedia.org/wiki/XPath
47. 문제를 향하여 언어를 구부리기
https://query.yahooapis.com/v1/public/yql?q=select+*+from+
weather.forecast+where+woeid=1132599&format=xml
<yweather:location xmlns:yweather="http://xml.weather.yahoo.com/ns/rss/1.0" city="Seoul" country="South
Korea" region=" Seoul"/>
48. 문제를 향하여 언어를 구부리기
<yweather:location xmlns:yweather="http://xml.weather.yahoo.com/ns/rss/1.0" city="Seoul" country="South
Korea" region=" Seoul"/>
import scala.io.Source
import scala.xml._
val
weatherURL="https://query.yahooapis.com/v1/public/yql?q=select+*+from+weather.forecast+where+woeid=1132
599&format=xml"
val xmlString = Source fromURL weatherURL mkString
val xml = XML loadString xmlString
val city = xml "location" "@city“
println(city)
println(city.getClass)
//Seoul
//class scala.xml.NodeSeq$$anon$1
50. 문제를 향하여 언어를 구부리기
xml "forecast" foreach (forecast => {
val date = forecast "@date"
val weather = forecast "@text"
println("date : "+date + ", weather : " + weather)
})
date : 12 Apr 2017, weather : Partly Cloudy
date : 13 Apr 2017, weather : Mostly Sunny
date : 14 Apr 2017, weather : Showers
date : 15 Apr 2017, weather : Scattered Thunderstorms
date : 16 Apr 2017, weather : Cloudy
date : 17 Apr 2017, weather : Rain
date : 18 Apr 2017, weather : Partly Cloudy
date : 19 Apr 2017, weather : Scattered Thunderstorms
date : 20 Apr 2017, weather : Scattered Thunderstorms
date : 21 Apr 2017, weather : Partly Cloudy
51. 문제를 향하여 언어를 구부리기
왜 JSON Lib
는 기본적으로
지원하지 않나
요?
나 때는 XML이 제
일 잘 나갔어..
• Scala를 만든 마틴 오더스키가 Scala 언어를 만들 당시에는
XML이 주류로 사용되고 있어, JSON은 고려하지 않았음
52. 디스패치 다시 생각하기
• 학점 계산기
– 매개변수가 숫자일 때
• 90 ~ 100 : A 리턴
• 80 ~ 90 : B 리턴
• 70 ~ 80 : C 리턴
• 60 ~ 70 : D 리턴
• 0 ~ 60 : F 리턴
– 매개변수가 글자일 때
• A~F or a~f 일 때, 해당 점수를 대문자로 변환하여 리턴
– 그 외
• Exception 처리
53. 디스패치 다시 생각하기
• Java
HashSet<Character> VALID_GRADES = new HashSet<Character>(){{
add('A');add('B');add('C');add('D');add('F');
}};
String gradeFromScore(Object score){
if(score instanceof Integer){
int s = (int) score;
if(90 <= s && s <= 100)
return "A";
if(80 <= s && s <= 90)
return "B";
if(70 <= s && s <= 80)
return "C";
if(60 <= s && s <= 70)
return "D";
if(0 <= s && s <= 60)
return "F";
} else if(score instanceof String){
if(VALID_GRADES.contains(((String) score).toUpperCase()))
return ((String) score).toUpperCase();
}
return “WrongCase”;
}
54. 디스패치 다시 생각하기
• Scala (패턴 매칭)
val VALID_GRADES = Set("A", "B", "C", "D", "F")
def letterGrade(value: Any) : String = value match {
case x:Int if (90 to 100).contains(x) => "A"
case x:Int if (80 to 90).contains(x) => "B"
case x:Int if (70 to 80).contains(x) => "C"
case x:Int if (60 to 70).contains(x) => "D"
case x:Int if (0 to 60).contains(x) => "F"
case x:String if VALID_GRADES(x.toUpperCase) => x.toUpperCase
}
55. 디스패치 다시 생각하기
• Groovy
def gradeFromScore(score) {
switch (score) {
case 90..100 : return "A"
case 80..<90 : return "B"
case 70..<80 : return "C"
case 60..<70 : return "D"
case 0..<60 : return "F"
case ~"[ABCDFabcdf]" : return score.toUpperCase()
default: throw new IllegalArgumentException("Invalid score: ${score}")
}
}
56. 디스패치 다시 생각하기
• Clojure
(defn in [score low high]
(and (number? score) (<= low score high)))
(defn letter-grade [score]
(cond
(in score 90 100) "A"
(in score 80 90) "B"
(in score 70 80) "C"
(in score 60 70) "D"
(in score 0 60) "F"
(re-find #"[ABCDFabcdf]" score) (.toUpperCase score)))
57. 함수형 자료구조
• 함수형 언어들은 예외 패러다임을 지원하지 않기 때
문에 다른 방법으로 우회
• 부수효과가 없는 순수함수, 참조 투명성 선호
• Java의 일반적인 예외 전파 방식을 우회
-> 타입 세이프(type-safe) 오류 처리 방식
58. 함수형 자료구조
• 함수형 오류처리
– Java는 메서드가 하나의 값만 리턴할 수 있다는 근본적인
제약
– Map을 사용하여 우회
public static Map<String, Object> divide(int a, int b){
Map<String, Object> result = new HashMap<>();
if(b == 0)
result.put("EXCEPTION", new Exception("divide by zero"));
else
result.put("ANSWER", (double) a/b);
return result;
}
public static void test(Map<String, Object> result){
if(result.get("EXCEPTION") == null){
System.out.println("Exception : " +
((Exception)result.get("EXCEPTION")).getMessage());
}else{
System.out.println("Answer : " + (double)result.get("ANSWER"));
}
}
test(divide(6,3));
test(divide(6,0));
//Answer : 2.0
//Exception : divide by zero
59. 함수형 자료구조
• 함수형 오류처리
– Scala - Either class
type Error = String
type Success = Double
def divide(a:Int, b:Int):Either[Error, Success] = {
if(b == 0)
Left("divide by zero")
else
Right(a/b)
}
def test(result:Either[Error, Success]) = result match {
case Left(msg) => println("Exception : " + msg)
case Right(answer) => println("Answer : " + answer)
}
test(divide(6,3))
test(divide(6,0))
//Answer : 2.0
//Exception : divide by zero
60. 함수형 자료구조
• Either class 이용 사례 (책 참고..)
– 게으른 파싱(Lazy Parser)
– 디폴트 값 제공
– 예외 조건 래핑
– 패턴 매칭과의 결합을 통한 장점 극대화
• Clojure, Groovy는 리턴 값을 쉽게 생성할 수 있는 동
적 타이핑 언어이기 때문에, Either가 굳이 필요 없음
61. 함수형 자료구조
• Option class - Scala
def divide(a:Int, b:Int): Option[Double] = {
if(b == 0)
None
else
Some(a/b)
}
def test(result:Option[Double]) = result match {
case None => println("Exception !!")
case Some(answer) => println("Answer : " + answer)
}
test(divide(6,3))
test(divide(6,0))
//Answer : 2.0
//Exception !!
63. 함수형 언어의 디자인 패턴
• 패턴이 언어에 흡수됨
• 패턴 해법이 함수형 패러다임에도 존재하지만, 구체
적인 구현 방식은 다름
• 해법이 다른 언어나 패러다임에 없는 기능으로 구현
64. 함수형 언어의 디자인 패턴
• 커플링 X, 큰 단위의 재사용 메커니즘 추출
– 커플링 : 구조물들 간에 잘 알려진 관계
• 목록(List) 중심으로 재사용 매커니즘 구축을 위해 상
황에 따라 달라지고 이동 가능한 코드 사용
65. 함수형 언어의 디자인 패턴
• 일급 함수를 매개변수나 리턴 값으로 사용
– 일급 함수(First-class function) : 언어의 다른 구조물들이 사
용되는 모든 곳에서 사용될 수 있는 함수
• 스캐폴딩이나 보일러 플레이트를 사용하지 않고 전
통적인 디자인 패턴의 문제 해결 가능
– 클로저를 지원하는 언어에서는 커맨드(명령) 디자인 패턴이
필요 없음
66. 함수형 언어의 디자인 패턴
• 템플릿 메서드 - Groovy
– 전통적 템플릿 메서드
– Customer 클래스를 상속받은 하위 클래스가
추상 메서드의 정의를 제공해야함
abstract class Customer {
def plan
def Customer() { plan = [] }
def abstract checkCredit()
def abstract checkInventory()
def abstract ship()
def process() {
checkCredit()
checkInventory()
ship()
}
}
67. 함수형 언어의 디자인 패턴
• 일급 함수를 사용한 템플릿 메서드
class Customer{
def plan, checkCredit, checkInventory, ship
def CustomerBlocksWithProtection() {
plan = []
}
def process() {
checkCredit()
checkInventory()
ship()
}
}
def VIPCustomer = new Customer()
VIPCustomer.ship = { println("VIP Ship ~~") }
def NormalCustomer = new Customer()
NormalCustomer.ship =
{ println("Ship Ship ~~") }
VIPCustomer.ship()
NormalCustomer.process()
//VIP Ship ~~
//Exception in thread "main"
//java.lang.NullPointerException
68. 함수형 언어의 디자인 패턴
• 일급 함수를 사용한 템플릿 메서드
• 보일러플레이트 코드가 필요 없음
class Customer{
def plan, checkCredit, checkInventory, ship
def CustomerBlocksWithProtection() {
plan = []
}
def process() {
checkCredit?.call()
checkInventory?.call()
ship?.call()
}
}
def VIPCustomer = new Customer()
VIPCustomer.ship = { println("VIP Ship ~~") }
def NormalCustomer = new Customer()
NormalCustomer.ship =
{ println("Ship Ship ~~") }
VIPCustomer.ship()
NormalCustomer.process()
//VIP Ship ~~
/Ship Ship ~~
69. 함수형 언어의 디자인 패턴
• 컴퓨터 종류를 모델링한 간단한 클래스
class Computer {
def type, cpu, memory, hardDrive, cd
}
class Desktop extends Computer {
def driveBays, fanWattage, videoCard
}
class Laptop extends Computer {
def usbPorts, dockingBay
}
class AssignedComputer {
def computerType, userId
public AssignedComputer(computerType, userId) {
this.computerType = computerType
this.userId = userId
}
}
70. 함수형 언어의 디자인 패턴
• 싱글턴 팩토리 + 플라이 웨이트 패턴
class CompFactory {
def types = [:]
static def instance
private ComputerFactory() {
def laptop = new Laptop()
def tower = new Desktop()
types.put("MacBookPro6_2", laptop)
types.put("SunTower", tower)
}
static def getInstance() {
if (instance == null)
instance = new CompFactory()
instance
}
def ofType(computer) {
types[computer]
}
}
class Computer {
def type, cpu, memory, hardDrive, cd
}
class Desktop extends Computer {
def driveBays, fanWattage, videoCard
}
class Laptop extends Computer {
def usbPorts, dockingBay
}
class AssignedComputer {
def computerType, userId
public AssignedComputer(computerType, userId) {
this.computerType = computerType
this.userId = userId
}
}
71. 함수형 언어의 디자인 패턴
• @singleton 사용 : 싱글턴을 단순화
@Singleton(strict = false) class ComputerFactory {
def types = [:]
private ComputerFactory() {
def laptop = new Laptop()
def tower = new Desktop()
types.put("MacBookPro6_2", laptop)
types.put("SunTower", tower)
}
def ofType(computer) {
types[computer]
}
}
def bob = new AssignedComputer(
ComputerFactory.instance.ofType("MacBookPro6_2"),
"Bob")
class Computer {
def type, cpu, memory, hardDrive, cd
}
class Desktop extends Computer {
def driveBays, fanWattage, videoCard
}
class Laptop extends Computer {
def usbPorts, dockingBay
}
class AssignedComputer {
def computerType, userId
public AssignedComputer(computerType, userId) {
this.computerType = computerType
this.userId = userId
}
}
72. 함수형 언어의 디자인 패턴
• 플라이웨이트를 메모아이즈하기
– 결과는 같지만, 캐싱을 런타임에 맡겨버림
@Singleton(strict = false) class ComputerFactory {
def types = [:]
private ComputerFactory() {
def laptop = new Laptop()
def tower = new Desktop()
types.put("MacBookPro6_2", laptop)
types.put("SunTower", tower)
}
def ofType(computer) {
types[computer]
}
}
def bob = new AssignedComputer(
ComputerFactory.instance.ofType("MacBookPro6_2"),
"Bob")
def computerOf = {type ->
def of =
[MacBookPro6_2: new Laptop(), SunTower: new Desktop()]
return of[type]
}
def computerOfType = computerOf.memoize()
def sally = new AssignedComputer(
computerOfType("MacBookPro6_2"), "Sally")
77. 함수형 인프라스트럭처
• 아키텍처 – 불변 클래스
– 모든 필드를 final로 선언
– 클래스를 final로 선언해서 오버라이드를 방지
– 인수가 없는 생성자를 제공하지 않음
– 적어도 하나의 생성자를 제공
– 생성자 외에는 변이 메서드를 제공하지 않음
78. 함수형 인프라스트럭처
• 웹 프레임워크
– 경로 설정(routing) 프레임워크
• 순회 가능한 표준적 자료구조 - vector 안에 vector가 들어있는 식
– 함수를 목적지로 사용
• Request를 받아서 Response를 리턴
– 도메인 특화 언어(DSL)
• Ruby On Rails, C# LINQ
– 빌드 도구와의 밀접한 연동
• 커맨드라인 빌드 도구
79. 함수형 인프라스트럭처
• 데이터베이스
– 모든 스키마와 데이터의 변화를 영원히 기록하기
• 스키마 조작을 포함한 모든 것이 저장 유지되어 이전 버전으로 돌아가기 쉬움
– 읽기와 쓰기의 분리
• CQRS 아키텍쳐 (책 참고)
– 이벤트 주도 아키텍처를 위한 불변성과 타임스탬프
• 어플리케이션 상태 변화를 이벤트 스트림으로 저장
81. MOOC
• Functional Programming in Scala Specialization
– https://www.coursera.org/specializations/scala
– Professor : Martin Odersky
– Scala 언어를 만든 Martin Odersky의 강의
82. MOOC
• C9 Lectures: Erik Meijer - Functional
Programming Fundamentals
– https://channel9.msdn.com/Series/C9-Lectures-Erik-Meijer-Functional-
Programming-Fundamentals
– Instructor : Erik Meijer
– Haskell 언어를 이용한 함수형 프로그래밍 강의
83. Book
• 브루스 테이트의 세븐 랭귀지
– http://book.naver.com/bookdb/book_detail.nhn?bid=8989923
– 저자 : 브루스 테이트
– Scala, Haskell, Clojure 등의 언어를 맛볼 수 있음
84. Book
• 브루스 테이트의 세븐 랭귀지
– http://book.naver.com/bookdb/book_detail.nhn?bid=8989923
– 저자 : 브루스 테이트
– Scala, Haskell, Clojure 등의 언어를 맛볼 수 있음
85. Book
• 7가지 동시성 모델
– http://book.naver.com/bookdb/book_detail.nhn?bid=10794699
– 저자 : 폴 부처
– Java, Scala, Clojure, Elixir 등의 함수형 프로그래밍으로 동시성과 분산
컴퓨팅 문제를 다룸
86. Book
• 스칼라로 배우는 함수형 프로그래밍
– http://book.naver.com/bookdb/book_detail.nhn?bid=8829454
– 저자 : 폴 키우사노, 루나르 비아르드나손
– Scala 언어를 이용해 함수형 프로그래밍의 원리를 알 수 있음
– 진짜 어려움