일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- Kotlin
- 아키텍처
- 객체지향의사실과오해
- 유지보수
- GrokkingFunctionalProgramming
- 테스트
- 스터디
- 책스터디
- 코틀린
- 계층형아키텍처
- Boot Legacy 차이점
- 헥사고날아키텍처
- 클린아키텍처
- 개발서적
- Spring
- Java
- TDD
- web
- 이펙티브코틀린
- 함수형프로그래밍
- 도메인 주도 개발 시작하기
- 조영호
- Thymeleaf
- 테스트주도개발
- 개발방법론
- FP
- 추상화 설계
- template
- 만들면서배우는클린아키텍처
- DDD
- Today
- Total
김동형수 개발기
Grokking Functional Programming - 1부 3장 본문
Grokking Functional Programming - 1부 3장
김동형수 2022. 11. 23. 22:573장 불변 변수
이 장에서 배울 것입니다
- 가변성이 위험한 이유
- 사본으로 작업하여 가변성과 싸우는 방법은 무엇입니까?
- 공유 가변 상태는 무엇입니까?
- 불변 값으로 작업하여 가변성과 싸우는 방법
- 문자열 및 목록 의 불변 API를 사용하는 방법
3.1 엔진 연료
순수함수가 가변 상태를 사용할 수 없는 이유를 설명한다.
순수 함수와 불변 값 사이의 관계는 매우 강해서 다음 두 가지 개념만 사용하여 함수형 프로그래밍을 정의할 수 있습니다.
Q 절대 변경될 수 없는 순수한 함수와 값만을 사용하여 완전히 작동하는 애플리케이션을 작성하는 것이 어떻게 가능합니까?
A 짧은 대답은 순수 함수가 데이터의 복사본을 만들어 전달하는 것입니다. 사본을 사용하여 쉽게 프로그래밍할 수 있으려면 언어의 특정 구조가 필요합니다. 이 장과 다음 장에서 더 긴 답변을 읽으면 더 많은 것을 알 수 있습니다.
3.2 불변성의 또 다른 경우
유럽여행
List<String> planA = new ArrayList<>();
planA.add("Paris");
planA.add("Berlin");
planA.add("Kraków");
System.out.println("Plan A: " + planA);
console output: Plan A: [Paris, Berlin, Kraków]
우리의 임무는 업데이트된 계획을 반환하는 재계획 기능 을 작성하는 것입니다. 세 가지 매개변수가 필요합니다.
- 변경하려는 계획(예: [Paris, Berlin, Kraków] ),
- 추가하려는 새 도시(예: Vienna ) 및
- 새로운 도시가 추가되어야 하는 도시(예: Kraków ).
아래처럼 시그니처가 작성되어야 한다.
3.4 가변성은 위험하다
3.5 거짓말을 하는 함수... 다시
· 단일 값만 반환합니다.
· 인수에 따라서만 반환 값을 계산합니다.
· 기존 값을 변경하지 않습니다.
static List<String> replan(List<String> plan,
String newCity,
String beforeCity) {
int newCityIndex = plan.indexOf(beforeCity);
plan.add(newCityIndex, newCity);
return plan;
}
위의 replan은 순수함수가 아니다.
이유 - 매개변수로 받은 plan을 변경했기 때문이다.
3.6 복사본으로 작업하여 가변성에 맞서기
static List<String> replan(List<String> plan,
String newCity,
String beforeCity) {
int newCityIndex = plan.indexOf(beforeCity);
List<String> replanned = new ArrayList<>(plan);
replanned.add(newCityIndex, newCity);
return replanned;
}
순수 함수는 기존 값을 변경하지 않습니다. 인수 목록이나 전역 범위에서 아무 것도 수정할 수 없습니다. 그러나 로컬로 생성된 값을 변경할 수 있습니다.
3.7 쉬는 시간: 가변성으로 인한 화상
static double totalTime(List<Double> lapTimes) {
lapTimes.remove(0);
double sum = 0;
for (double x : lapTimes) {
sum += x;
}
return sum;
}
static double avgTime(List<Double> lapTimes) {
double time = totalTime(lapTimes);
int laps = lapTimes.size();
return time / laps;
}
· avgTime 은 워밍업 랩을 제외한 평균 랩 시간을 반환해야 합니다.
· 최소 2개의 랩이 있는 목록만 전달됩니다.
내 풀이
static double totalTime(List<Double> lapTimes) {
var copiedLapTimes = new ArrayList<Double>(lapTimes)
copiedLapTimes.remove(0)
double sum = 0;
for (double x : lapTimes) {
sum += x;
}
return sum;
}
static double avgTime(List<Double> lapTimes) {
var copiedLapTimes = new ArrayList<Double>(lapTimes)
copiedLapTimes.remove(0)
return totalTime(lapTimes) / copiedLapTimes.size();
}
3.9 공유 가변 상태 소개
3.10 프로그래밍 능력에 대한 상태의 영향
첫째, 프로그래밍 문제를 해결하기 위해 많은 것을 염두에 두어야 하고 일반적으로 그렇게 하는 경우 이러한 사항이 함수 호출 사이 또는 심지어 두 줄의 코드 사이(스레드를 사용하여 프로그래밍할 때) 언제든지 변경될 수 있다면 문제는 훨씬 더 어려워집니다.
둘째, 이렇게 시시각각 변하는 것들이 추가로 공유된다면 그에 대한 소유권과 책임의 문제가 생긴다. "이 값을 안전하게 변경할 수 있습니까?", "프로그램의 다른 부분에서 이 값을 사용합니까?", "이 값을 변경하면 이 변경 사항에 대해 어떤 엔터티에 알려야 합니까?"라는 질문을 끊임없이 스스로에게 해야 합니다.
셋째, 많은 개체가 주어진 상태를 변경할 수 있는 경우 이 상태의 모든 가능한 값을 식별하는 데 문제가 있을 수 있습니다. 이 상태가 당면한 코드에 의해서만 생성될 수 있는 값을 가지고 있다고 가정하는 것은 매우 유혹적입니다. 그러나이 상태가 공유된다면 그것은 잘못된 가정입니다! 재계획 기능이 새 계획을 반환 하기 때문에 계획 이 생성되면 변경할 수 없다고 가정한 것을 기억 하십니까?
3.11 움직이는 부품 다루기
마지막으로 "움직이는 부분" 또는 공유된 가변 상태를 직접 다루는 기술에 대해 이야기할 수 있습니다.
세 가지 접근 방식을 소개합니다.
- 재계획 기능을 고쳤 을 때 사용한 방식
- 객체 지향 방식
- OOP에서는 변경되는 데이터를 보호하기 위해 캡슐화 를 사용합니다.
- 기능적 방식
3.12 FP를 이용한 가동부 처리
불변의 값
값이 생성되면 절대 변경할 수 없도록 보장하는 기술입니다. 프로그래머가 값의 아주 작은 부분이라도 변경해야 하는 경우(예: 목록에 문자열 추가) 새 값을 만들고 이전 값을 그대로 유지해야 합니다.
3.15 쉬는 시간: Immutable String API
def function(stringParameter: String): String = {
stringParameter.split(" ").zipWithIndex.map(string => {
if(string._2 == 0) string._1.substring(0, 1) + "."
else string._1
}).reduce((a, b) => a + " " + b)
}
3.18 공유 가변 상태에 대한 순수 함수적 접근
가치 사이의 관계에 집중
항상 들어오는 값과 생성하려는 값 사이의 모든 알려진 관계를 나열하는 것으로 시작하는 것입니다 .
3.20 요약
가변성은 위험하다
우리는 변경 가능한 컬렉션을 사용할 때 특별한 주의를 기울여야 한다는 것을 발견했습니다.
서명을 보는 것만으로는 충분하지 않습니다.
복사본을 사용한 가변성과의 싸움
공유 가변 상태란 무엇입니까?
코드베이스의 서로 다른 엔터티 간에 공유되고 변경될 수 있는 변수인 공유 변경 가능 상태를 도입했습니다.
불변 값을 사용하여 가변성과 싸우기
마지막으로 공유된 가변 상태를 처리하기 위해 더 강력한 기술인 불변 값을 도입했습니다. 함수가 변경 불가능한 값만 취하고 변경 불가능한 값을 반환한다면 예기치 않게 변경된 것이 없다고 확신할 수 있습니다.
문자열 및 목록 의 불변 API 사용
결국 우리는 Java의 String 이 이미 이 접근 방식을 사용하고 있음을 알게 되었습니다. 많은 메서드가 String 의 새 값을 반환하기 때문 입니다. 우리는 Scala가 불변 콜렉션을 기본적으로 지원한다는 것을 배웠고 List의 slice , append 및 appendAll 함수를 약간 사용해 보았습니다. 우리는 모든 종류의 불변 값에 대해 학습하는 데 책의 나머지 부분을 할애할 것입니다.
'책 스터디 > [완료] FP - Grokking Funtional Programming' 카테고리의 다른 글
Grokking Functional Programming - 2부 6장 (0) | 2022.12.21 |
---|---|
Grokking Functional Programming - 2부 5장 (0) | 2022.12.14 |
Grokking Functional Programming - 1부 4장 (0) | 2022.11.30 |
Grokking Functional Programming - 1부 2장 (0) | 2022.11.16 |
Grokking Functional Programming - 1부 1장 (0) | 2022.11.09 |