SlideShare a Scribd company logo
Functional Thinking
심재문
Neal ford – 함수형 사고
https://github.com/oreillymedia/func
tional_thinking
CHAPTER 1
왜?
문제 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 …
문제 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 …
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;
}
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;
}
기존 OOP
• 움직이는 부분(mutable)을 캡슐화하여 코드 이해를 도움
• 캡슐화, 스코핑, 가시성 등의 메커니즘
• 상태(state) 변화를 위한 세밀한 제어
• Class마다 고유한 자료구조 - GOF 디자인 패턴
• 쓰레드까지 고려하면 어휴…
함수형 프로그래밍
• 움직이는 부분을 제거(Immutable)
• 최적화된 몇몇 자료구조만 사용(list, set, map)
• 자료구조 + 고계함수 (고 수준의 추상화)
• 고계함수(higher-order function)
– 아래 두 가지 사항 중, 적어도 하나 만족
– 하나 이상의 함수를 매개변수로 취함
– 함수의 결과를 함수로 반환
regexToList(companies, "w+").stream()
.filter(w -> !EXCLUSION.contains(w))
CHAPTER 2
전환
문제 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
Pseudocode
listOfCompanies
-> filter(x.length > 1)
-> transform(x.capitalize)
-> convert(x + “,” + y)
• 필터, 변형, 변환 등의 논리적 분류를 저수준의 변형
으로 구현
• 고계함수에서 주어지는 함수를 이용하여 저수준의
작업을 커스터마이즈
Java 8
listOfCompanies
-> filter(x.length > 1)
-> transform(x.capitalize)
-> convert(x + “,” + y)
private String capitalize(String e){
return e.substring(0,1).toUpperCase() + e.substring(1, e.length());
}
public String processCompanies(List<String> companies){
return companies.stream()
.filter(company -> company != null)
.filter(company -> company.length() > 1)
.map(company -> capitalize(company))
.collect(Collectors.joining(","));
}
고수준 추상화의 장점
• 문제점의 공통점을 고려하여 다른 방식으로 분류
• 런타임이 알아서 최적화
• 개발자가 엔진 세부 사항에 깊이 파묻힐 경우 불가능
한 해답을 가능하게 함
– ex) 멀티 쓰레드 문제
여러 쓰레드에서...?
public String processCompanies(List<String> companies){
return companies.parallelStream()
.filter(company -> company != null)
.filter(company -> company.length() > 1)
.map(company -> capitalize(company))
.collect(Collectors.joining(","));
}
• 병렬 Collection 사용
공통된 빌딩블록
filter(num -> num % 2 == 0)
• 필터
– 원래 목록보다 작은 목록을 생성
1 2 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7 8 9 10
공통된 빌딩블록
map(num -> num * 2 + 1)
• 맵
– 각 요소에 같은 함수를 적용하여 새 컬렉션으로 만듦
1 2 3 4 5 6 7 8 9 10
3 5 7 9 11 13 15 17 19 21
Map i * 2 + 1
공통된 빌딩블록
foldLeft(0)(_ + _) // scala code
• 폴드/리듀스
– 누산기(accumulator)를 사용해 값을 모음
– 캐터모피즘(카테고리 이론)의 변형
1 2 30
1
3
6
누산기 목록연산
+
2 3
3
CHAPTER 3
양도하라
클로저 (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
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)
클로저 (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
클로저 (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
커링과 부분 적용
• 수학자 해스켈 커리(Haskell Brooks Curry) 등에서 유
래
• 함수나 메서드의 인수(parameter)의 개수를 조작
커링과 부분 적용
• 커링(Currying)
– 다 인수 함수를 일 인수 함수들의 체인으로 바꾸는
func(a,b,c) -> func(a)(b)(c),func(a), func(a)(b)
• 부분 적용 (Partial application)
– 다 인수 함수의 생략될 인수의 값을 미리 정해서 더 적은 수
의 인수를 받는 하나의 함수로 변경
func(a,b,c) -> func(a,b)
커링(Currying)
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)
def modN(n: Int)(x: Int) = ((x % n) == 0)
val nums = List(1, 2, 3, 4, 5, 6, 7, 8)
println(filter(nums, modN(2)))
//List(2, 4, 6, 8)
println(filter(nums, modN(3)))
//List(3, 6)
// Scala example
부분 적용(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
재귀
• 꼬리 호출 최적화(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)
CHAPTER 4
열심히보다는 현명하게
메모이제이션(memoization)
• 영국의 인공지능 학자 도널드 미치가 처음 사용
• 연속해서 사용되는 연산 값을 함수 레벨에서 캐시
• 동적 프로그래밍(Dynamic Programming)
메모이제이션(memoization)
• 캐싱 방법이 제대로 작동하려면? => 순수 함수
• 순수 함수
– 부수 효과가 없는 함수
– 불변 클래스 필드를 참고하지 않음
– 리턴 값 외에는 아무 값도 쓰지 않음
– 주어진 매개 변수에만 의존
– ex) java.lang.Math
문제 3
- 계단 오르기
당신은 계단을 오르고 있습니다.
꼭대기까지 오르기 위해 N개의 계단을 올라가야 합니다.
매번 1 or 2개의 계단을 올라갈 수 있습니다.
계단을 올라가는 방법이 몇 개가 있을까요?
N : 양의 정수
https://leetcode.com/problems/climbing-stairs/#/description
문제 3
- 계단 오르기
1
2
3 ...
N-1
N
N-2
문제 3
- 계단 오르기 Pseudocode
function climb(int n)
if n is 0 or 1
return 1
else
return climb(n-1) + climb(n-2)
문제 3
- 계단 오르기 c++
int climb(int n) {
if (n == 0 || n == 1)
return 1;
return climb(n - 1) + climb(n - 2);
}
문제 3
- 계단 오르기 c++
int climb(int n) {
if (n == 0 || n == 1)
return 1;
return climb(n - 1) + climb(n - 2);
}
n이 1000이면...?
너무 느리다...
문제 3
- 계단 오르기 c++ (memoization)
#define MAX_N 1000
int cache[MAX_N + 1];
void init() { memset(cache, -1, sizeof(cache)); }
int climb(int n) {
if (n == 0 || n == 1)
return 1;
int &ret = cache[n];
if (ret != -1)
return ret;
return ret = climb(n - 1) + climb(n - 2);
}
문제 3
- 계단 오르기 groovy
- memoize() 제공
def climb
climb = { n->
(n == 0 || n == 1) ? 1 : climb(n - 2) + climb(n - 1)
}.memoize()
climb.call(5)
문제 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)
문제 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))
문제 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)
게으름(Lazy evaluation)
• 시간이 많이 걸리는 연산을 반드시 필요할 때까지 미
룸
• 요청이 계속되는 한 요소를 계속 전달하는 무한 컬렉
션을 만들 수 있음
• 맵이나 필터 같은 함수형 개념을 게으르게 사용하면,
효율이 높은 코드를 만들 수 있음
게으름(Lazy evaluation)
• collect()를 호출하기 전까지, 아무런 연산이 일어나지
않음
private String capitalize(String e){
return e.substring(0,1).toUpperCase() + e.substring(1, e.length());
}
public String processCompanies(List<String> companies){
return companies.stream()
.filter(company -> company != null)
.filter(company -> company.length() > 1)
.map(company -> capitalize(company))
.collect(Collectors.joining(","));
}
CHAPTER 5
진화하라
문제를 향하여 언어를 구부리기
• Java는 언어로써 유연하지 못하기 때문에, 아이디어
를 기존의 고정된 구조에 맞게 주물러야 함
• Scala는 내부 DSL(Domain Specific Language)을 지
원하기 위해 설계된 언어
• Clojure와 같은 모든 Lisp 계열 언어들도 문제에 맞게
언어를 바꾸는 유연성이 좋음
문제를 향하여 언어를 구부리기
• Scala : Xpath 쿼리를 언어 자체에서 지원
• Xpath : XML Path Language
• https://ko.wikipedia.org/wiki/XPath
문제를 향하여 언어를 구부리기
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"/>
문제를 향하여 언어를 구부리기
<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
문제를 향하여 언어를 구부리기
<yweather:forecast xmlns:yweather="http://xml.weather.yahoo.com/ns/rss/1.0" code="12" date="11 Apr
2017" day="Tue" high="69" low="53" text="Rain"/>
<yweather:forecast xmlns:yweather="http://xml.weather.yahoo.com/ns/rss/1.0" code="34" date="12 Apr
2017" day="Wed" high="60" low="44" text="Mostly Sunny"/>
<yweather:forecast xmlns:yweather="http://xml.weather.yahoo.com/ns/rss/1.0" code="34" date="13 Apr
2017" day="Thu" high="66" low="40" text="Mostly Sunny"/>
<yweather:forecast xmlns:yweather="http://xml.weather.yahoo.com/ns/rss/1.0" code="47" date="14 Apr
2017" day="Fri" high="61" low="48" text="Scattered Thunderstorms"/>
<yweather:forecast xmlns:yweather="http://xml.weather.yahoo.com/ns/rss/1.0" code="47" date="15 Apr
2017" day="Sat" high="66" low="51" text="Scattered Thunderstorms"/>
...
문제를 향하여 언어를 구부리기
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
문제를 향하여 언어를 구부리기
왜 JSON Lib
는 기본적으로
지원하지 않나
요?
나 때는 XML이 제
일 잘 나갔어..
• Scala를 만든 마틴 오더스키가 Scala 언어를 만들 당시에는
XML이 주류로 사용되고 있어, JSON은 고려하지 않았음
디스패치 다시 생각하기
• 학점 계산기
– 매개변수가 숫자일 때
• 90 ~ 100 : A 리턴
• 80 ~ 90 : B 리턴
• 70 ~ 80 : C 리턴
• 60 ~ 70 : D 리턴
• 0 ~ 60 : F 리턴
– 매개변수가 글자일 때
• A~F or a~f 일 때, 해당 점수를 대문자로 변환하여 리턴
– 그 외
• Exception 처리
디스패치 다시 생각하기
• 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”;
}
디스패치 다시 생각하기
• 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
}
디스패치 다시 생각하기
• 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}")
}
}
디스패치 다시 생각하기
• 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)))
함수형 자료구조
• 함수형 언어들은 예외 패러다임을 지원하지 않기 때
문에 다른 방법으로 우회
• 부수효과가 없는 순수함수, 참조 투명성 선호
• Java의 일반적인 예외 전파 방식을 우회
-> 타입 세이프(type-safe) 오류 처리 방식
함수형 자료구조
• 함수형 오류처리
– 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
함수형 자료구조
• 함수형 오류처리
– 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
함수형 자료구조
• Either class 이용 사례 (책 참고..)
– 게으른 파싱(Lazy Parser)
– 디폴트 값 제공
– 예외 조건 래핑
– 패턴 매칭과의 결합을 통한 장점 극대화
• Clojure, Groovy는 리턴 값을 쉽게 생성할 수 있는 동
적 타이핑 언어이기 때문에, Either가 굳이 필요 없음
함수형 자료구조
• 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 !!
CHAPTER 6
전진하라
함수형 언어의 디자인 패턴
• 패턴이 언어에 흡수됨
• 패턴 해법이 함수형 패러다임에도 존재하지만, 구체
적인 구현 방식은 다름
• 해법이 다른 언어나 패러다임에 없는 기능으로 구현
함수형 언어의 디자인 패턴
• 커플링 X, 큰 단위의 재사용 메커니즘 추출
– 커플링 : 구조물들 간에 잘 알려진 관계
• 목록(List) 중심으로 재사용 매커니즘 구축을 위해 상
황에 따라 달라지고 이동 가능한 코드 사용
함수형 언어의 디자인 패턴
• 일급 함수를 매개변수나 리턴 값으로 사용
– 일급 함수(First-class function) : 언어의 다른 구조물들이 사
용되는 모든 곳에서 사용될 수 있는 함수
• 스캐폴딩이나 보일러 플레이트를 사용하지 않고 전
통적인 디자인 패턴의 문제 해결 가능
– 클로저를 지원하는 언어에서는 커맨드(명령) 디자인 패턴이
필요 없음
함수형 언어의 디자인 패턴
• 템플릿 메서드 - Groovy
– 전통적 템플릿 메서드
– Customer 클래스를 상속받은 하위 클래스가
추상 메서드의 정의를 제공해야함
abstract class Customer {
def plan
def Customer() { plan = [] }
def abstract checkCredit()
def abstract checkInventory()
def abstract ship()
def process() {
checkCredit()
checkInventory()
ship()
}
}
함수형 언어의 디자인 패턴
• 일급 함수를 사용한 템플릿 메서드
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
함수형 언어의 디자인 패턴
• 일급 함수를 사용한 템플릿 메서드
• 보일러플레이트 코드가 필요 없음
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 ~~
함수형 언어의 디자인 패턴
• 컴퓨터 종류를 모델링한 간단한 클래스
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
}
}
함수형 언어의 디자인 패턴
• 싱글턴 팩토리 + 플라이 웨이트 패턴
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
}
}
함수형 언어의 디자인 패턴
• @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
}
}
함수형 언어의 디자인 패턴
• 플라이웨이트를 메모아이즈하기
– 결과는 같지만, 캐싱을 런타임에 맡겨버림
@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")
CHAPTER 7
실용적 사고
Java 8
• 함수형 인터페이스
– Runnable, Callable 같은 단일 추상 메서드
(single abstract method - SAM)
– 함수형 인터페이스는 람다와 SAM이 유용하게 상호작용
new Thread(() -> System.out.println("Inside thread!!")).start();
Java 8
• 함수형 인터페이스
– 하나의 함수형 인터페이스는 하나의 SAM을 포함하며, 여러
개의 디폴트 메서드도 함께 포함 가능
– 디폴트 메서드 : 인터페이스 안에 default로 표시되는 public,
nonabstract, nonstatic 메서드
Java 8
• 함수형 인터페이스
– 디폴트 메서드 예제
for(int i=0; i<list.size(); i++)
System.out.println(list.get(i));
for(String str : list)
System.out.println(str);
list.forEach(System.out::println); //default method
함수형 인프라스트럭처
• 아키텍처 – 불변 클래스
– 모든 필드를 final로 선언
– 클래스를 final로 선언해서 오버라이드를 방지
– 인수가 없는 생성자를 제공하지 않음
– 적어도 하나의 생성자를 제공
– 생성자 외에는 변이 메서드를 제공하지 않음
함수형 인프라스트럭처
• 웹 프레임워크
– 경로 설정(routing) 프레임워크
• 순회 가능한 표준적 자료구조 - vector 안에 vector가 들어있는 식
– 함수를 목적지로 사용
• Request를 받아서 Response를 리턴
– 도메인 특화 언어(DSL)
• Ruby On Rails, C# LINQ
– 빌드 도구와의 밀접한 연동
• 커맨드라인 빌드 도구
함수형 인프라스트럭처
• 데이터베이스
– 모든 스키마와 데이터의 변화를 영원히 기록하기
• 스키마 조작을 포함한 모든 것이 저장 유지되어 이전 버전으로 돌아가기 쉬움
– 읽기와 쓰기의 분리
• CQRS 아키텍쳐 (책 참고)
– 이벤트 주도 아키텍처를 위한 불변성과 타임스탬프
• 어플리케이션 상태 변화를 이벤트 스트림으로 저장
BONUS
MOOC
• Functional Programming in Scala Specialization
– https://www.coursera.org/specializations/scala
– Professor : Martin Odersky
– Scala 언어를 만든 Martin Odersky의 강의
MOOC
• C9 Lectures: Erik Meijer - Functional
Programming Fundamentals
– https://channel9.msdn.com/Series/C9-Lectures-Erik-Meijer-Functional-
Programming-Fundamentals
– Instructor : Erik Meijer
– Haskell 언어를 이용한 함수형 프로그래밍 강의
Book
• 브루스 테이트의 세븐 랭귀지
– http://book.naver.com/bookdb/book_detail.nhn?bid=8989923
– 저자 : 브루스 테이트
– Scala, Haskell, Clojure 등의 언어를 맛볼 수 있음
Book
• 브루스 테이트의 세븐 랭귀지
– http://book.naver.com/bookdb/book_detail.nhn?bid=8989923
– 저자 : 브루스 테이트
– Scala, Haskell, Clojure 등의 언어를 맛볼 수 있음
Book
• 7가지 동시성 모델
– http://book.naver.com/bookdb/book_detail.nhn?bid=10794699
– 저자 : 폴 부처
– Java, Scala, Clojure, Elixir 등의 함수형 프로그래밍으로 동시성과 분산
컴퓨팅 문제를 다룸
Book
• 스칼라로 배우는 함수형 프로그래밍
– http://book.naver.com/bookdb/book_detail.nhn?bid=8829454
– 저자 : 폴 키우사노, 루나르 비아르드나손
– Scala 언어를 이용해 함수형 프로그래밍의 원리를 알 수 있음
– 진짜 어려움
Q & A
감사합니다

More Related Content

What's hot

R 스터디 세번째
R 스터디 세번째R 스터디 세번째
R 스터디 세번째
Jaeseok Park
 
R과 기초통계 : 02.기술통계-자료나타내기
R과 기초통계 : 02.기술통계-자료나타내기R과 기초통계 : 02.기술통계-자료나타내기
R과 기초통계 : 02.기술통계-자료나타내기
Yoonwhan Lee
 
Tensorflow regression 텐서플로우 회귀
Tensorflow regression 텐서플로우 회귀Tensorflow regression 텐서플로우 회귀
Tensorflow regression 텐서플로우 회귀
beom kyun choi
 
영상 데이터의 처리와 정보의 추출
영상 데이터의 처리와 정보의 추출영상 데이터의 처리와 정보의 추출
영상 데이터의 처리와 정보의 추출
동윤 이
 
Python+numpy pandas 2편
Python+numpy pandas 2편Python+numpy pandas 2편
Python+numpy pandas 2편
Yong Joon Moon
 
Just java
Just javaJust java
Just java
Jong Wook Kim
 
해커에게 전해들은 머신러닝 #3
해커에게 전해들은 머신러닝 #3해커에게 전해들은 머신러닝 #3
해커에게 전해들은 머신러닝 #3
Haesun Park
 
iOS 메모리관리
iOS 메모리관리iOS 메모리관리
iOS 메모리관리
Changwon National University
 
하스켈 모나드
하스켈 모나드하스켈 모나드
하스켈 모나드
Kwang Yul Seo
 
빠르게 활용하는 파이썬3 스터디(ch1~4)
빠르게 활용하는 파이썬3 스터디(ch1~4)빠르게 활용하는 파이썬3 스터디(ch1~4)
빠르게 활용하는 파이썬3 스터디(ch1~4)SeongHyun Ahn
 
Python 활용: 이미지 처리와 데이터 분석
Python 활용: 이미지 처리와 데이터 분석Python 활용: 이미지 처리와 데이터 분석
Python 활용: 이미지 처리와 데이터 분석
용 최
 
해커에게 전해들은 머신러닝 #2
해커에게 전해들은 머신러닝 #2해커에게 전해들은 머신러닝 #2
해커에게 전해들은 머신러닝 #2
Haesun Park
 
Fp basic-kotlin
Fp basic-kotlinFp basic-kotlin
Fp basic-kotlin
Myeongin Woo
 
How2heap
How2heap How2heap
How2heap
Seonghwan Cho
 
R 프로그래밍을 이용한 야생동물 행동권(HR) 분석
R 프로그래밍을 이용한 야생동물 행동권(HR) 분석R 프로그래밍을 이용한 야생동물 행동권(HR) 분석
R 프로그래밍을 이용한 야생동물 행동권(HR) 분석
Byeong-Hyeok Yu
 
Python machine learning Ch.4
Python machine learning Ch.4Python machine learning Ch.4
Python machine learning Ch.4
PartPrime
 
해커에게 전해들은 머신러닝 #4
해커에게 전해들은 머신러닝 #4해커에게 전해들은 머신러닝 #4
해커에게 전해들은 머신러닝 #4
Haesun Park
 
알고리즘 스터디(정렬) Seungdols
알고리즘 스터디(정렬) Seungdols알고리즘 스터디(정렬) Seungdols
알고리즘 스터디(정렬) Seungdols
seungdols
 

What's hot (20)

R 스터디 세번째
R 스터디 세번째R 스터디 세번째
R 스터디 세번째
 
R과 기초통계 : 02.기술통계-자료나타내기
R과 기초통계 : 02.기술통계-자료나타내기R과 기초통계 : 02.기술통계-자료나타내기
R과 기초통계 : 02.기술통계-자료나타내기
 
Tensorflow regression 텐서플로우 회귀
Tensorflow regression 텐서플로우 회귀Tensorflow regression 텐서플로우 회귀
Tensorflow regression 텐서플로우 회귀
 
영상 데이터의 처리와 정보의 추출
영상 데이터의 처리와 정보의 추출영상 데이터의 처리와 정보의 추출
영상 데이터의 처리와 정보의 추출
 
Python+numpy pandas 2편
Python+numpy pandas 2편Python+numpy pandas 2편
Python+numpy pandas 2편
 
Just java
Just javaJust java
Just java
 
해커에게 전해들은 머신러닝 #3
해커에게 전해들은 머신러닝 #3해커에게 전해들은 머신러닝 #3
해커에게 전해들은 머신러닝 #3
 
iOS 메모리관리
iOS 메모리관리iOS 메모리관리
iOS 메모리관리
 
하스켈 모나드
하스켈 모나드하스켈 모나드
하스켈 모나드
 
빠르게 활용하는 파이썬3 스터디(ch1~4)
빠르게 활용하는 파이썬3 스터디(ch1~4)빠르게 활용하는 파이썬3 스터디(ch1~4)
빠르게 활용하는 파이썬3 스터디(ch1~4)
 
Python 활용: 이미지 처리와 데이터 분석
Python 활용: 이미지 처리와 데이터 분석Python 활용: 이미지 처리와 데이터 분석
Python 활용: 이미지 처리와 데이터 분석
 
해커에게 전해들은 머신러닝 #2
해커에게 전해들은 머신러닝 #2해커에게 전해들은 머신러닝 #2
해커에게 전해들은 머신러닝 #2
 
R_datamining
R_dataminingR_datamining
R_datamining
 
Fp basic-kotlin
Fp basic-kotlinFp basic-kotlin
Fp basic-kotlin
 
How2heap
How2heap How2heap
How2heap
 
R 프로그래밍을 이용한 야생동물 행동권(HR) 분석
R 프로그래밍을 이용한 야생동물 행동권(HR) 분석R 프로그래밍을 이용한 야생동물 행동권(HR) 분석
R 프로그래밍을 이용한 야생동물 행동권(HR) 분석
 
Python machine learning Ch.4
Python machine learning Ch.4Python machine learning Ch.4
Python machine learning Ch.4
 
해커에게 전해들은 머신러닝 #4
해커에게 전해들은 머신러닝 #4해커에게 전해들은 머신러닝 #4
해커에게 전해들은 머신러닝 #4
 
R intro
R introR intro
R intro
 
알고리즘 스터디(정렬) Seungdols
알고리즘 스터디(정렬) Seungdols알고리즘 스터디(정렬) Seungdols
알고리즘 스터디(정렬) Seungdols
 

Similar to 함수형 사고 - Functional thinking

Scala, Scalability
Scala, ScalabilityScala, Scalability
Scala, Scalability
Dongwook Lee
 
3ds maxscript 튜토리얼_20151206_서진택
3ds maxscript 튜토리얼_20151206_서진택3ds maxscript 튜토리얼_20151206_서진택
3ds maxscript 튜토리얼_20151206_서진택
JinTaek Seo
 
GKAC 2014 Nov. - 안드로이드 스튜디오로 생산성 올리기
GKAC 2014 Nov. - 안드로이드 스튜디오로 생산성 올리기GKAC 2014 Nov. - 안드로이드 스튜디오로 생산성 올리기
GKAC 2014 Nov. - 안드로이드 스튜디오로 생산성 올리기
GDG Korea
 
함수적 사고 2장
함수적 사고 2장함수적 사고 2장
함수적 사고 2장
HyeonSeok Choi
 
2014.07.26 KSUG와 지앤선이 함께하는 테크니컬 세미나 - 나의 첫번째 자바8 람다식 (정대원)
2014.07.26 KSUG와 지앤선이 함께하는 테크니컬 세미나 - 나의 첫번째 자바8 람다식 (정대원)2014.07.26 KSUG와 지앤선이 함께하는 테크니컬 세미나 - 나의 첫번째 자바8 람다식 (정대원)
2014.07.26 KSUG와 지앤선이 함께하는 테크니컬 세미나 - 나의 첫번째 자바8 람다식 (정대원)
JiandSon
 
불어오는 변화의 바람, From c++98 to c++11, 14
불어오는 변화의 바람, From c++98 to c++11, 14 불어오는 변화의 바람, From c++98 to c++11, 14
불어오는 변화의 바람, From c++98 to c++11, 14
명신 김
 
파이썬 기본 문법
파이썬 기본 문법파이썬 기본 문법
파이썬 기본 문법
SeongHyun Ahn
 
Java Annotation과 MyBatis로 나만의 ORM Framework을 만들어보자
Java Annotation과 MyBatis로 나만의 ORM Framework을 만들어보자Java Annotation과 MyBatis로 나만의 ORM Framework을 만들어보자
Java Annotation과 MyBatis로 나만의 ORM Framework을 만들어보자
Donghyeok Kang
 
스플렁크 머신러닝 연동
스플렁크 머신러닝 연동스플렁크 머신러닝 연동
스플렁크 머신러닝 연동
Seung-Woo Kang
 
스플렁크 Machine Learning Integration
스플렁크 Machine Learning Integration스플렁크 Machine Learning Integration
스플렁크 Machine Learning Integration
TIMEGATE
 
TABLE ACCESS 패턴을 이용한 SQL 튜닝_Wh oracle
TABLE ACCESS 패턴을 이용한 SQL 튜닝_Wh oracleTABLE ACCESS 패턴을 이용한 SQL 튜닝_Wh oracle
TABLE ACCESS 패턴을 이용한 SQL 튜닝_Wh oracle
엑셈
 
[Main Session] 미래의 Java 미리보기 - 앰버와 발할라 프로젝트를 중심으로
[Main Session] 미래의 Java 미리보기 - 앰버와 발할라 프로젝트를 중심으로[Main Session] 미래의 Java 미리보기 - 앰버와 발할라 프로젝트를 중심으로
[Main Session] 미래의 Java 미리보기 - 앰버와 발할라 프로젝트를 중심으로
Oracle Korea
 
Java.next
Java.nextJava.next
Java.next
Sungchul Park
 
파이썬 스터디 2주차
파이썬 스터디 2주차파이썬 스터디 2주차
파이썬 스터디 2주차
Han Sung Kim
 
공간데이터베이스(Spatial db)
공간데이터베이스(Spatial db)공간데이터베이스(Spatial db)
공간데이터베이스(Spatial db)
H.J. SIM
 
//BUILD/ Seoul - .NET의 현재와 미래. 그 새로운 시작
//BUILD/ Seoul - .NET의 현재와 미래. 그 새로운 시작//BUILD/ Seoul - .NET의 현재와 미래. 그 새로운 시작
//BUILD/ Seoul - .NET의 현재와 미래. 그 새로운 시작
Taeyoung Kim
 
R project_pt1
R project_pt1R project_pt1
R project_pt1
Joonho Lee
 
PySpark 배우기 Ch 06. ML 패키지 소개하기
PySpark 배우기 Ch 06. ML 패키지 소개하기PySpark 배우기 Ch 06. ML 패키지 소개하기
PySpark 배우기 Ch 06. ML 패키지 소개하기
찬희 이
 

Similar to 함수형 사고 - Functional thinking (20)

Scalability
ScalabilityScalability
Scalability
 
Scala, Scalability
Scala, ScalabilityScala, Scalability
Scala, Scalability
 
3ds maxscript 튜토리얼_20151206_서진택
3ds maxscript 튜토리얼_20151206_서진택3ds maxscript 튜토리얼_20151206_서진택
3ds maxscript 튜토리얼_20151206_서진택
 
GKAC 2014 Nov. - 안드로이드 스튜디오로 생산성 올리기
GKAC 2014 Nov. - 안드로이드 스튜디오로 생산성 올리기GKAC 2014 Nov. - 안드로이드 스튜디오로 생산성 올리기
GKAC 2014 Nov. - 안드로이드 스튜디오로 생산성 올리기
 
함수적 사고 2장
함수적 사고 2장함수적 사고 2장
함수적 사고 2장
 
2014.07.26 KSUG와 지앤선이 함께하는 테크니컬 세미나 - 나의 첫번째 자바8 람다식 (정대원)
2014.07.26 KSUG와 지앤선이 함께하는 테크니컬 세미나 - 나의 첫번째 자바8 람다식 (정대원)2014.07.26 KSUG와 지앤선이 함께하는 테크니컬 세미나 - 나의 첫번째 자바8 람다식 (정대원)
2014.07.26 KSUG와 지앤선이 함께하는 테크니컬 세미나 - 나의 첫번째 자바8 람다식 (정대원)
 
불어오는 변화의 바람, From c++98 to c++11, 14
불어오는 변화의 바람, From c++98 to c++11, 14 불어오는 변화의 바람, From c++98 to c++11, 14
불어오는 변화의 바람, From c++98 to c++11, 14
 
파이썬 기본 문법
파이썬 기본 문법파이썬 기본 문법
파이썬 기본 문법
 
Scala
ScalaScala
Scala
 
Java Annotation과 MyBatis로 나만의 ORM Framework을 만들어보자
Java Annotation과 MyBatis로 나만의 ORM Framework을 만들어보자Java Annotation과 MyBatis로 나만의 ORM Framework을 만들어보자
Java Annotation과 MyBatis로 나만의 ORM Framework을 만들어보자
 
스플렁크 머신러닝 연동
스플렁크 머신러닝 연동스플렁크 머신러닝 연동
스플렁크 머신러닝 연동
 
스플렁크 Machine Learning Integration
스플렁크 Machine Learning Integration스플렁크 Machine Learning Integration
스플렁크 Machine Learning Integration
 
TABLE ACCESS 패턴을 이용한 SQL 튜닝_Wh oracle
TABLE ACCESS 패턴을 이용한 SQL 튜닝_Wh oracleTABLE ACCESS 패턴을 이용한 SQL 튜닝_Wh oracle
TABLE ACCESS 패턴을 이용한 SQL 튜닝_Wh oracle
 
[Main Session] 미래의 Java 미리보기 - 앰버와 발할라 프로젝트를 중심으로
[Main Session] 미래의 Java 미리보기 - 앰버와 발할라 프로젝트를 중심으로[Main Session] 미래의 Java 미리보기 - 앰버와 발할라 프로젝트를 중심으로
[Main Session] 미래의 Java 미리보기 - 앰버와 발할라 프로젝트를 중심으로
 
Java.next
Java.nextJava.next
Java.next
 
파이썬 스터디 2주차
파이썬 스터디 2주차파이썬 스터디 2주차
파이썬 스터디 2주차
 
공간데이터베이스(Spatial db)
공간데이터베이스(Spatial db)공간데이터베이스(Spatial db)
공간데이터베이스(Spatial db)
 
//BUILD/ Seoul - .NET의 현재와 미래. 그 새로운 시작
//BUILD/ Seoul - .NET의 현재와 미래. 그 새로운 시작//BUILD/ Seoul - .NET의 현재와 미래. 그 새로운 시작
//BUILD/ Seoul - .NET의 현재와 미래. 그 새로운 시작
 
R project_pt1
R project_pt1R project_pt1
R project_pt1
 
PySpark 배우기 Ch 06. ML 패키지 소개하기
PySpark 배우기 Ch 06. ML 패키지 소개하기PySpark 배우기 Ch 06. ML 패키지 소개하기
PySpark 배우기 Ch 06. ML 패키지 소개하기
 

함수형 사고 - Functional thinking

  • 2. Neal ford – 함수형 사고 https://github.com/oreillymedia/func tional_thinking
  • 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
  • 12. Pseudocode listOfCompanies -> filter(x.length > 1) -> transform(x.capitalize) -> convert(x + “,” + y) • 필터, 변형, 변환 등의 논리적 분류를 저수준의 변형 으로 구현 • 고계함수에서 주어지는 함수를 이용하여 저수준의 작업을 커스터마이즈
  • 13. Java 8 listOfCompanies -> filter(x.length > 1) -> transform(x.capitalize) -> convert(x + “,” + y) private String capitalize(String e){ return e.substring(0,1).toUpperCase() + e.substring(1, e.length()); } public String processCompanies(List<String> companies){ return companies.stream() .filter(company -> company != null) .filter(company -> company.length() > 1) .map(company -> capitalize(company)) .collect(Collectors.joining(",")); }
  • 14. 고수준 추상화의 장점 • 문제점의 공통점을 고려하여 다른 방식으로 분류 • 런타임이 알아서 최적화 • 개발자가 엔진 세부 사항에 깊이 파묻힐 경우 불가능 한 해답을 가능하게 함 – ex) 멀티 쓰레드 문제
  • 15. 여러 쓰레드에서...? public String processCompanies(List<String> companies){ return companies.parallelStream() .filter(company -> company != null) .filter(company -> company.length() > 1) .map(company -> capitalize(company)) .collect(Collectors.joining(",")); } • 병렬 Collection 사용
  • 16. 공통된 빌딩블록 filter(num -> num % 2 == 0) • 필터 – 원래 목록보다 작은 목록을 생성 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10
  • 17. 공통된 빌딩블록 map(num -> num * 2 + 1) • 맵 – 각 요소에 같은 함수를 적용하여 새 컬렉션으로 만듦 1 2 3 4 5 6 7 8 9 10 3 5 7 9 11 13 15 17 19 21 Map i * 2 + 1
  • 18. 공통된 빌딩블록 foldLeft(0)(_ + _) // scala code • 폴드/리듀스 – 누산기(accumulator)를 사용해 값을 모음 – 캐터모피즘(카테고리 이론)의 변형 1 2 30 1 3 6 누산기 목록연산 + 2 3 3
  • 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)
  • 26. 커링(Currying) 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) def modN(n: Int)(x: Int) = ((x % n) == 0) val nums = List(1, 2, 3, 4, 5, 6, 7, 8) println(filter(nums, modN(2))) //List(2, 4, 6, 8) println(filter(nums, modN(3))) //List(3, 6) // Scala example
  • 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)
  • 30. 메모이제이션(memoization) • 영국의 인공지능 학자 도널드 미치가 처음 사용 • 연속해서 사용되는 연산 값을 함수 레벨에서 캐시 • 동적 프로그래밍(Dynamic Programming)
  • 31. 메모이제이션(memoization) • 캐싱 방법이 제대로 작동하려면? => 순수 함수 • 순수 함수 – 부수 효과가 없는 함수 – 불변 클래스 필드를 참고하지 않음 – 리턴 값 외에는 아무 값도 쓰지 않음 – 주어진 매개 변수에만 의존 – ex) java.lang.Math
  • 32. 문제 3 - 계단 오르기 당신은 계단을 오르고 있습니다. 꼭대기까지 오르기 위해 N개의 계단을 올라가야 합니다. 매번 1 or 2개의 계단을 올라갈 수 있습니다. 계단을 올라가는 방법이 몇 개가 있을까요? N : 양의 정수 https://leetcode.com/problems/climbing-stairs/#/description
  • 33. 문제 3 - 계단 오르기 1 2 3 ... N-1 N N-2
  • 34. 문제 3 - 계단 오르기 Pseudocode function climb(int n) if n is 0 or 1 return 1 else return climb(n-1) + climb(n-2)
  • 35. 문제 3 - 계단 오르기 c++ int climb(int n) { if (n == 0 || n == 1) return 1; return climb(n - 1) + climb(n - 2); }
  • 36. 문제 3 - 계단 오르기 c++ int climb(int n) { if (n == 0 || n == 1) return 1; return climb(n - 1) + climb(n - 2); } n이 1000이면...? 너무 느리다...
  • 37. 문제 3 - 계단 오르기 c++ (memoization) #define MAX_N 1000 int cache[MAX_N + 1]; void init() { memset(cache, -1, sizeof(cache)); } int climb(int n) { if (n == 0 || n == 1) return 1; int &ret = cache[n]; if (ret != -1) return ret; return ret = climb(n - 1) + climb(n - 2); }
  • 38. 문제 3 - 계단 오르기 groovy - memoize() 제공 def climb climb = { n-> (n == 0 || n == 1) ? 1 : climb(n - 2) + climb(n - 1) }.memoize() climb.call(5)
  • 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) • 시간이 많이 걸리는 연산을 반드시 필요할 때까지 미 룸 • 요청이 계속되는 한 요소를 계속 전달하는 무한 컬렉 션을 만들 수 있음 • 맵이나 필터 같은 함수형 개념을 게으르게 사용하면, 효율이 높은 코드를 만들 수 있음
  • 43. 게으름(Lazy evaluation) • collect()를 호출하기 전까지, 아무런 연산이 일어나지 않음 private String capitalize(String e){ return e.substring(0,1).toUpperCase() + e.substring(1, e.length()); } public String processCompanies(List<String> companies){ return companies.stream() .filter(company -> company != null) .filter(company -> company.length() > 1) .map(company -> capitalize(company)) .collect(Collectors.joining(",")); }
  • 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
  • 49. 문제를 향하여 언어를 구부리기 <yweather:forecast xmlns:yweather="http://xml.weather.yahoo.com/ns/rss/1.0" code="12" date="11 Apr 2017" day="Tue" high="69" low="53" text="Rain"/> <yweather:forecast xmlns:yweather="http://xml.weather.yahoo.com/ns/rss/1.0" code="34" date="12 Apr 2017" day="Wed" high="60" low="44" text="Mostly Sunny"/> <yweather:forecast xmlns:yweather="http://xml.weather.yahoo.com/ns/rss/1.0" code="34" date="13 Apr 2017" day="Thu" high="66" low="40" text="Mostly Sunny"/> <yweather:forecast xmlns:yweather="http://xml.weather.yahoo.com/ns/rss/1.0" code="47" date="14 Apr 2017" day="Fri" high="61" low="48" text="Scattered Thunderstorms"/> <yweather:forecast xmlns:yweather="http://xml.weather.yahoo.com/ns/rss/1.0" code="47" date="15 Apr 2017" day="Sat" high="66" low="51" text="Scattered Thunderstorms"/> ...
  • 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")
  • 74. Java 8 • 함수형 인터페이스 – Runnable, Callable 같은 단일 추상 메서드 (single abstract method - SAM) – 함수형 인터페이스는 람다와 SAM이 유용하게 상호작용 new Thread(() -> System.out.println("Inside thread!!")).start();
  • 75. Java 8 • 함수형 인터페이스 – 하나의 함수형 인터페이스는 하나의 SAM을 포함하며, 여러 개의 디폴트 메서드도 함께 포함 가능 – 디폴트 메서드 : 인터페이스 안에 default로 표시되는 public, nonabstract, nonstatic 메서드
  • 76. Java 8 • 함수형 인터페이스 – 디폴트 메서드 예제 for(int i=0; i<list.size(); i++) System.out.println(list.get(i)); for(String str : list) System.out.println(str); list.forEach(System.out::println); //default method
  • 77. 함수형 인프라스트럭처 • 아키텍처 – 불변 클래스 – 모든 필드를 final로 선언 – 클래스를 final로 선언해서 오버라이드를 방지 – 인수가 없는 생성자를 제공하지 않음 – 적어도 하나의 생성자를 제공 – 생성자 외에는 변이 메서드를 제공하지 않음
  • 78. 함수형 인프라스트럭처 • 웹 프레임워크 – 경로 설정(routing) 프레임워크 • 순회 가능한 표준적 자료구조 - vector 안에 vector가 들어있는 식 – 함수를 목적지로 사용 • Request를 받아서 Response를 리턴 – 도메인 특화 언어(DSL) • Ruby On Rails, C# LINQ – 빌드 도구와의 밀접한 연동 • 커맨드라인 빌드 도구
  • 79. 함수형 인프라스트럭처 • 데이터베이스 – 모든 스키마와 데이터의 변화를 영원히 기록하기 • 스키마 조작을 포함한 모든 것이 저장 유지되어 이전 버전으로 돌아가기 쉬움 – 읽기와 쓰기의 분리 • CQRS 아키텍쳐 (책 참고) – 이벤트 주도 아키텍처를 위한 불변성과 타임스탬프 • 어플리케이션 상태 변화를 이벤트 스트림으로 저장
  • 80. BONUS
  • 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 언어를 이용해 함수형 프로그래밍의 원리를 알 수 있음 – 진짜 어려움
  • 87. Q & A