Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
Functional Thinking
Ch2. 전환
아꿈사
Cecil
함수형 코드를 작성하기 위해서는
프로그래밍 언어의 전환이 필요한 것이 아니라
문제에 접근하는 방식의 전환이 필요
명령형 처리 vs 함수형 처리
예제: 문자열 연결
명령형 처리(Java)
public class TheCompanyProcess {

public String cleanNames(List<String> listOfNames) {

StringBuilder result ...
함수형 처리(scala)
val employees = List("neal", "s", "stu", "j", "rich", "bob", "aiden",
"j", "ethan", "liam", "mason", "noah",...
무엇이 다른가?
명령형 처리: How를 기술
함수형 처리: What을 기술
문자열 예제의 What?
1. len(x) > 1인 큰 문자열을 찾음
2. 대문자로 변환
3. 문자열을 연결
Java 8
public class Process {

public String cleanNames(List<String> names) {

if (names == null) return "";

return names...
Groovy
public class TheCompanyProcess {

public static String cleanUpNames(listOfNames) {

listOfNames

.findAll { it.leng...
Clojure
; 기본적인 clojure 버전
; 리스프 계열 언어는 안에서 밖으로 실행됨.

(defn process [list-of-emps]

(reduce str (interpose ","

(map s/capi...
함수형 사고로의 전환은?
세부적인 구현에 뛰어들지 않고
고수준의 추상 개념을 적용하는 것
고수준 추상적 사고의 이점
문제를 다른 시각에서 분류할 수 있게 함
런타임에 최적화가 가능(작업 순서 조정)
개발자가 엔진 세부사항을 고려하지 않으면 할 수 없던 일을
가능하게 함(ex: 병렬 처리)
고수준 추상화의 스레드 적용
// Scala

val parallelResult = employees

.par // 스레드로 처리

.filter(_.length() > 1)

.map(_.capitalize)

.r...
사례 연구
예제: 자연수의 분류
6(완전수) = 1 + 2 +3
분류 조건
완전수 N의 진약수의 합 = N
과잉수 N의 진약수의 합 > N
부족수 N의 진약수의 합 < N
명령형 자연수 분류
public class ImpNumberClassifierSimple {

private int _number;

private Map<Integer, Integer> _cache; // 내부 캐시
...
Java 8을 사용한 자연수 분류
public class NumberClassifier {

// 함수 호출시 실제 작업이 수행되는 것이 아님. stream을 반환

public static IntStream facto...
함수형 언어의 공통된 빌딩 블록
필터, 맵, 폴드/리듀스
필터
Figure 2-1. Filtering a list of numbers from a larger list
When filtering, you produce another list (or collection) pot...
맵
리스트의 각 요소에 같은 함수를 적용하여 새로운 리스트를 생성
// 약수 구하기 최적화 버전.

static def factors(number) {

def factors = (1..round(sqrt(number)...
폴드/리듀스
Figure 2-3. Fold operation
Because addition is commutative, it doesn’t matter if you do a foldLeft() or fold
Right(...
언어별 용어 차이
필터
• Scala
• filter, partition, find, takeWhile, DropWhile
• Groovy
• findAll(filter), split(partition), takeWhile, DropWh...
맵
• Scala
• map, flatMap
• Groovy
• collect(Map), flatten(flatMap)
• Clojure
• map, flatten(flatMap)
폴드/리듀스
• Scala
• reduceLeft, reduceRight, foldLeft, foldRight
• Groovy
• inject(reduce)
• Clojure
• reduce
References
•Neal Ford, Functional Thinking(김재완 옮김). 서울
시 마포구 양화로 한빛미디어, 2016.
Upcoming SlideShare
Loading in …5
×

함수적 사고 2장

537 views

Published on

함수적 사고 2장 아꿈사 발표 자료

Published in: Software
  • Login to see the comments

함수적 사고 2장

  1. 1. Functional Thinking Ch2. 전환 아꿈사 Cecil
  2. 2. 함수형 코드를 작성하기 위해서는 프로그래밍 언어의 전환이 필요한 것이 아니라 문제에 접근하는 방식의 전환이 필요
  3. 3. 명령형 처리 vs 함수형 처리 예제: 문자열 연결
  4. 4. 명령형 처리(Java) public class TheCompanyProcess {
 public String cleanNames(List<String> listOfNames) {
 StringBuilder result = new StringBuilder();
 for (int i = 0; i < listOfNames.size(); i++) { // loop 사용이 일반적
 if (listOfNames.get(i).length() > 1) {
 // 한 문자 이상인 문자열을 연결
 result.append(capitalizeString(listOfNames.get(i))).append(",");
 }
 }
 return result.substring(0, result.length() - 1).toString();
 }
 
 public String capitalizeString(String s) {
 return s.substring(0, 1).toUpperCase() + s.substring(1, s.length());
 }
 }
  5. 5. 함수형 처리(scala) val employees = List("neal", "s", "stu", "j", "rich", "bob", "aiden", "j", "ethan", "liam", "mason", "noah", "lucas", "jacob", "jayden", “jack") 
 val result = employees
 .filter(_.length() > 1) // 필터
 .map(_.capitalize) // 변형(Transform)
 .reduce(_ + "," + _) // 변환(convert) 수학 공식을 모델링하는 표현과 변형으로 기술하며, 가변 상태를 지양
  6. 6. 무엇이 다른가? 명령형 처리: How를 기술 함수형 처리: What을 기술 문자열 예제의 What? 1. len(x) > 1인 큰 문자열을 찾음 2. 대문자로 변환 3. 문자열을 연결
  7. 7. Java 8 public class Process {
 public String cleanNames(List<String> names) {
 if (names == null) return "";
 return names.stream() // stream을 생성
 .filter(name -> name != null)
 .filter(name -> name.length() > 1)
 .map(name -> capitalize(name))
 .collect(Collectors.joining(",")); // reduce의 특별한 경우
 }
 
 private String capitalize(String e) {
 return e.substring(0, 1).toUpperCase() + e.substring(1, e.length());
 }
 }
  8. 8. Groovy public class TheCompanyProcess {
 public static String cleanUpNames(listOfNames) {
 listOfNames
 .findAll { it.length() > 1 } // 필터
 .collect { it.capitalize() } // 변형
 .join ',' // 변환
 }
 }
  9. 9. Clojure ; 기본적인 clojure 버전 ; 리스프 계열 언어는 안에서 밖으로 실행됨.
 (defn process [list-of-emps]
 (reduce str (interpose ","
 (map s/capitalize
 (filter #(< 1 (count %)) list-of-emps)
 ))))
 
 ; 매크로를 사용한 가독성 향상 버전
 (defn process2 [list-of-emps]
 (->> list-of-emps
 (filter #(< 1 (count %)))
 (map s/capitalize)
 (interpose ",")
 (reduce str)
 ))
  10. 10. 함수형 사고로의 전환은? 세부적인 구현에 뛰어들지 않고 고수준의 추상 개념을 적용하는 것
  11. 11. 고수준 추상적 사고의 이점 문제를 다른 시각에서 분류할 수 있게 함 런타임에 최적화가 가능(작업 순서 조정) 개발자가 엔진 세부사항을 고려하지 않으면 할 수 없던 일을 가능하게 함(ex: 병렬 처리)
  12. 12. 고수준 추상화의 스레드 적용 // Scala
 val parallelResult = employees
 .par // 스레드로 처리
 .filter(_.length() > 1)
 .map(_.capitalize)
 .reduce(_ + "," + _) // java 8
 public String cleanNamesP(List<String> names) { if (names == null) return "";
 return names
 .parallelStream() // 스레드로 처리
 .filter(n -> n.length() > 1)
 .map(e -> capitalize(e))
 .collect(Collectors.joining(","));
 }
  13. 13. 사례 연구 예제: 자연수의 분류 6(완전수) = 1 + 2 +3 분류 조건 완전수 N의 진약수의 합 = N 과잉수 N의 진약수의 합 > N 부족수 N의 진약수의 합 < N
  14. 14. 명령형 자연수 분류 public class ImpNumberClassifierSimple {
 private int _number;
 private Map<Integer, Integer> _cache; // 내부 캐시
 
 public ImpNumberClassifierSimple(int targetNumber) {
 _number = targetNumber;
 _cache = new HashMap<>();
 }
 // 약수인가?
 public boolean isFactor(int potential) {
 return _number % potential == 0;
 } 
 public boolean isPerfect() {
 return aliquotSum() == _number;
 }
 public boolean isAbundant() {
 return aliquotSum() > _number;
 }
 public boolean isDeficient() {
 return aliquotSum() < _number;
 } // 진약수 구하기
 public Set<Integer> getFactors() {
 Set<Integer> factors = new HashSet<>();
 factors.add(1);
 factors.add(_number);
 for (int i = 2; i < _number; i++)
 if (isFactor(i)) factors.add(i);
 return factors;
 }
 // 진약수의 합
 public int aliquotSum() {
 if (_cache.get(_number) == null) {
 int sum = 0;
 for (int i : getFactors())
 sum += i;
 _cache.put(_number, sum - _number);
 }
 return _cache.get(_number);
 }
 }
  15. 15. Java 8을 사용한 자연수 분류 public class NumberClassifier {
 // 함수 호출시 실제 작업이 수행되는 것이 아님. stream을 반환
 public static IntStream factorsOf(int number) {
 return range(1, number + 1)
 .filter(potential -> number % potential == 0);
 }
 // sum 내부에서 stream을 해석 
 public static int aliquotSum(int number) {
 return factorsOf(number).sum() - number;
 }
 
 public static boolean isPerfect(int number) {
 return aliquotSum(number) == number;
 }
 
 public static boolean isAbundant(int number) {
 return aliquotSum(number) > number;
 }
 
 public static boolean isDeficient(int number) {
 return aliquotSum(number) < number;
 }
 }
  16. 16. 함수형 언어의 공통된 빌딩 블록 필터, 맵, 폴드/리듀스
  17. 17. 필터 Figure 2-1. Filtering a list of numbers from a larger list When filtering, you produce another list (or collection) potentially smaller than the original, depending on the filtering criteria. In the number-classifier example, I use filtering to determine the factors of a number, as shown in Example 2-14. Example 2-14. Filtering in Java 8 public static IntStream factorsOf(int number) { return range(1, number + 1) .filter(potential -> number % potential == 0); } The code in Example 2-14 creates a range of numbers from 1 to the target number, then 사용자가 지정한 조건으로 목록을 더 작은 목록으로 만드는 작업 public static IntStream factorsOf(int number) {
 return range(1, number + 1)
 .filter(potential -> number % potential == 0);
 }
  18. 18. 맵 리스트의 각 요소에 같은 함수를 적용하여 새로운 리스트를 생성 // 약수 구하기 최적화 버전.
 static def factors(number) {
 def factors = (1..round(sqrt(number)+1)).findAll({number % it == 0})
 (factors + factors.collect {number / it}).unique()
 } Figure 2-2. Mapping a function onto a collection To illustrate map() and related transformations, I create an optimized version of my number classifier. First, I create an imperative version, shown in Example 2-16. Example 2-16. Number classifier optimized import java.util.HashMap; import java.util.HashSet;
  19. 19. 폴드/리듀스 Figure 2-3. Fold operation Because addition is commutative, it doesn’t matter if you do a foldLeft() or fold Right(). But some operations (including subtraction and division) care about order, so the foldRight() method exists to handle those cases. In purely functional languages, leftandrightfoldshaveimplementationdifferences.Forexample,rightfoldscanoperate on infinite lists whereas left folds cannot. Example 2-13 uses the Functional Java-supplied add enumeration; the framework in‐ cludes the most common mathematical operations for you. But what about cases in 누산기(Accumulator)를 사용해서 값을 모으는 작업 reduce, foldLeft => (f (f (f (f 0,N1) N2) N3) N4) foldRight => (f N1 (f N2 (f N3 (f N4 0)))) foldLeft
  20. 20. 언어별 용어 차이
  21. 21. 필터 • Scala • filter, partition, find, takeWhile, DropWhile • Groovy • findAll(filter), split(partition), takeWhile, DropWhile • Clojure • filter
  22. 22. 맵 • Scala • map, flatMap • Groovy • collect(Map), flatten(flatMap) • Clojure • map, flatten(flatMap)
  23. 23. 폴드/리듀스 • Scala • reduceLeft, reduceRight, foldLeft, foldRight • Groovy • inject(reduce) • Clojure • reduce
  24. 24. References •Neal Ford, Functional Thinking(김재완 옮김). 서울 시 마포구 양화로 한빛미디어, 2016.

×