코틀린을 다루는 기술
코틀린답게 코딩하자!
코틀린은 자바와 부드럽게 연동되는 우아한 JVM 언어로, 구글은 2019년부터 안드로이드에서 최우선 언어로 코틀린을 채택했다. 『코틀린을 다루는 기술』은 이해하기 쉽고 유지 보수하기 편하며 안전한 프로그램을 코틀린으로 작성하는 법을 가르쳐준다. 함수형 프로그래밍에서 영감을 얻은 다양한 기법을 소개하고 프로그래밍할 때 발생하는 일반적인 문제를 이 기법들로 해결하는 방법을 알려준다. 여러 문제를 해결해 나가는 과정에서 오류와 데이터를 제대로 처리하는 방법, 상태를 관리하는 방법, 지연 계산을 활용하는 방법 등을 배우게 된다. 이 책에 있는 강력한 기법들을 제대로 배우고 나면 코틀린을 깊이 있게 이해하고 현업에서 코틀린을 더 코틀린답게 사용할 수 있을 것이다.
«코틀린을 다루는 기술»은 1~3장을 공개합니다.
목차
- 1장 프로그램을 더 안전하게 만들기
- 1.1 프로그래밍의 함정
- 1.1.1 안전하게 부수 효과 처리하기
- 1.1.2 참조 투명성으로 프로그램을 더 안전하게 만들기
- 1.2 안전한 프로그래밍의 이점
- 1.2.1 프로그램을 추론하는 데 치환 모델 사용하기
- 1.2.2 안전성 원칙을 간단한 식에 적용하기
- 1.2.3 끝까지 추상화하기
- 1.3 요약
- 2장 코틀린 프로그래밍의 개요
- 2.1 필드와 변수
- 2.1.1 타입을 생략해 더 간단하게 만들기
- 2.1.2 가변 필드 사용하기
- 2.1.3 지연 초기화 이해하기
- 2.2 클래스와 인터페이스
- 2.2.1 예제 코드 간결하게 만들기
- 2.2.2 인터페이스를 구현하거나 클래스를 확장하기
- 2.2.3 클래스 인스턴스화하기
- 2.2.4 프로퍼티 생성자 오버로드하기
- 2.2.5 equals와 hashCode 메서드 만들기
- 2.2.6 데이터 객체 구조 분해하기
- 2.2.7 정적 메서드 구현하기
- 2.2.8 싱글턴 사용하기
- 2.2.9 유틸리티 클래스 인스턴스화 방지하기
- 2.3 원시 타입이 없음
- 2.4 컬렉션의 두 유형
- 2.5 패키지
- 2.6 가시성
- 2.7 함수
- 2.7.1 함수 선언하기
- 2.7.2 로컬 함수 사용하기
- 2.7.3 함수 오버라이드하기
- 2.7.4 확장 함수 사용하기
- 2.7.5 람다 사용하기
- 2.8 널
- 2.8.1 널이 될 수 있는 타입 다루기
- 2.8.2 엘비스 연산자와 기본 값
- 2.9 프로그램 흐름과 제어 구조
- 2.9.1 조건 선택 사용하기
- 2.9.2 다중 조건 선택 사용하기
- 2.9.3 루프 사용하기
- 2.10 비검사 예외
- 2.11 사용한 자원 자동으로 닫기
- 2.12 스마트 캐스트
- 2.13 동등성과 동일성
- 2.14 문자열 인터폴레이션
- 2.15 여러 줄 문자열
- 2.16 변성: 파라미터화한 타입과 하위 타입
- 2.16.1 변성이 문제인 이유
- 2.16.2 공변성을 써야 하는 경우와 반공변성을 써야 하는 경우
- 2.16.3 사용 지점 변성과 선언 지점 변성
- 2.17 요약
- 3장 함수로 프로그래밍하기
- 3.1 함수란 무엇인가
- 3.1.1 두 함수 집합 사이의 대응 관계 이해하기
- 3.1.2 코틀린 역함수
- 3.1.3 부분 함수 다루기
- 3.1.4 함수 합성 이해하기
- 3.1.5 인자를 여럿 받는 함수 사용하기
- 3.1.6 커리한 함수
- 3.1.7 부분 적용 함수 사용하기
- 3.1.8 효과가 없는 함수
- 3.2 코틀린 함수
- 3.2.1 함수를 데이터로 이해하기
- 3.2.2 데이터를 함수로 이해하기
- 3.2.3 객체 생성자를 함수로 사용하기
- 3.2.4 코틀린 fun 함수 사용하기
- 3.2.5 객체 표기법과 함수 표기법 비교
- 3.2.6 함수 값 사용하기
- 3.2.7 함수 참조 사용하기
- 3.2.8 함수 합성
- 3.2.9 함수 재사용하기
- 3.3 고급 함수 기능
- 3.3.1 인자가 여럿 있는 함수 처리하기
- 3.3.2 커리한 함수 적용하기
- 3.3.3 고차 함수 구현하기
- 3.3.4 다형적 HOF 정의하기
- 3.3.5 익명 함수 사용하기
- 3.3.6 로컬 함수 정의하기
- 3.3.7 클로저 구현하기
- 3.3.8 함수 부분 적용과 자동 커링
- 3.3.9 부분 적용 함수의 인자 뒤바꾸기
- 3.3.10 항등 함수 정의하기
- 3.3.11 올바른 타입 사용하기
- 3.4 요약
- 4장 재귀, 공재귀, 메모화
- 4.1 공재귀와 재귀
- 4.1.1 공재귀 구현하기
- 4.1.2 재귀 구현하기
- 4.1.3 재귀 함수와 공재귀 함수 구분하기
- 4.1.4 재귀 또는 공재귀 선택하기
- 4.2 꼬리 호출 제거
- 4.2.1 꼬리 호출 제거 사용하기
- 4.2.2 루프를 공재귀로 변환하기
- 4.2.3 재귀 함수 값 사용하기
- 4.3 재귀 함수와 리스트
- 4.3.1 이중 재귀 함수 사용하기
- 4.3.2 리스트에 대한 재귀 추상화하기
- 4.3.3 리스트 뒤집기
- 4.3.4 공재귀 리스트 만들기
- 4.3.5 즉시 계산의 위험성
- 4.4 메모화
- 4.4.1 루프를 사용하는 프로그래밍에서 메모화 사용하기
- 4.4.2 재귀 함수에서 메모화 사용하기
- 4.4.3 암시적 메모화 사용하기
- 4.4.4 자동 메모화 사용하기
- 4.4.5 다인자 함수의 메모화 구현하기
- 4.5 메모화한 함수는 순수 함수인가
- 4.6 요약
- 5장 리스트로 데이터 처리하기
- 5.1 데이터 컬렉션을 분류하는 방법
- 5.2 리스트의 여러 유형
- 5.3 리스트의 상대적 예상 성능
- 5.3.1 시간 복잡도와 공간 복잡도를 서로 맞바꾸기
- 5.3.2 제자리 상태 변이 피하기
- 5.4 코틀린에서 사용할 수 있는 리스트의 종류
- 5.4.1 영속적인 데이터 구조 사용하기
- 5.4.2 불변이며 영속적인 단일 연결 리스트 구현하기
- 5.5 리스트 연산에서 데이터 공유하기
- 5.6 다른 리스트 연산들
- 5.6.1 객체 표기법의 이점 살리기
- 5.6.2 리스트 연결
- 5.6.3 리스트의 끝에서부터 원소 제거하기
- 5.6.4 재귀와 고차 함수로 리스트 접기
- 5.6.5 변성 사용하기
- 5.6.6 스택을 안전하게 사용하는 foldRight 만들기
- 5.6.7 리스트 매핑과 필터링
- 5.7 요약
- 6장 선택적 데이터 처리하기
- 6.1 널 포인터의 문제점
- 6.2 코틀린이 널 참조를 처리하는 방식
- 6.3 널 참조에 대한 대안
- 6.4 Option 타입 사용하기
- 6.4.1 Option에서 값 가져오기
- 6.4.2 선택적 값에 함수 적용하기
- 6.4.3 Option 합성 처리하기
- 6.4.4 Option 사용 예
- 6.4.5 Option을 조합하는 다른 방법
- 6.4.6 Option으로 List 합성하기
- 6.4.7 Option을 언제 사용할까
- 6.5 요약
- 7장 오류와 예외 처리하기
- 7.1 데이터가 없는 경우와 관련한 문제점
- 7.2 Either 타입
- 7.3 Result 타입
- 7.4 Result 패턴
- 7.5 고급 Result 처리
- 7.5.1 술어 적용하기
- 7.6 실패 매핑하기
- 7.7 팩터리 함수 추가하기
- 7.8 효과 적용하기
- 7.9 고급 Result 합성
- 7.10 요약
- 8장 고급 리스트 처리
- 8.1 length의 단점
- 8.2 성능 문제
- 8.3 메모화의 이점
- 8.3.1 메모화의 단점 처리하기
- 8.3.2 성능 향상 평가하기
- 8.4 List와 Result의 합성
- 8.4.1 Result를 반환하는 리스트 처리하기
- 8.4.2 List
를 Result - 로 변환하기
- 8.5 리스트에 대한 일반적인 추상화
- 8.5.2 인덱스로 원소 접근하기
- 8.5.3 리스트 나누기
- 8.5.4 부분 리스트 검색하기
- 8.5.5 리스트를 처리하는 다른 함수들
- 8.5.1 리스트를 묶거나 풀기
- 8.6 리스트를 자동으로 병렬 처리하기
- 8.6.1 모든 계산을 병렬화할 수는 없다
- 8.6.2 리스트를 부분 리스트로 나누기
- 8.6.3 부분 리스트를 병렬로 처리하기
- 8.7 요약
- 9장 지연 계산 사용하기
- 9.1 즉시 계산과 지연 계산
- 9.2 코틀린과 즉시 계산
- 9.3 코틀린과 지연 계산
- 9.4 지연 계산 구현
- 9.4.1 지연 값 합성하기
- 9.4.2 함수 끌어올리기
- 9.4.3 Lazy 값 매핑하고 매핑 후 펼치기
- 9.4.4 Lazy와 List 합성하기
- 9.4.5 예외 다루기
- 9.5 추가 지연 합성
- 9.5.1 효과를 지연 계산으로 적용하기
- 9.5.2 지연 계산이 없으면 할 수 없는 일
- 9.5.3 지연 리스트 데이터 구조 만들기
- 9.6 스트림 처리하기
- 9.6.1 스트림 접기
- 9.6.2 평가와 함수 적용 추적하기
- 9.6.3 스트림을 구체적인 문제에 적용하기
- 9.7 요약
- 10장 트리를 사용한 데이터 처리
- 10.1 이진 트리
- 10.2 균형 트리와 불균형 트리 이해하기
- 10.3 트리의 크기, 높이, 깊이 살펴보기
- 10.4 빈 트리와 트리의 재귀적 정의
- 10.5 잎 트리
- 10.6 순서가 있는 이진 트리와 이진 검색 트리
- 10.7 삽입 순서와 트리의 구조
- 10.8 재귀적 트리 순회 순서와 비재귀적 트리 순회 순서
- 10.8.1 재귀적으로 트리 순회하기
- 10.8.2 비재귀적 순회 순서
- 10.9 이진 검색 트리 구현
- 10.9.1 변성과 트리 이해하기
- 10.9.2 Tree 클래스의 추상 함수로 구현하는 방법은 어떨까
- 10.9.3 연산자 오버로딩
- 10.9.4 트리에 대해 재귀 사용하기
- 10.9.5 트리에서 원소 제거하기
- 10.9.6 임의의 트리 합병하기
- 10.10 트리 접기에 대해
- 10.10.1 두 함수를 사용해 접기
- 10.10.2 함수를 하나만 사용해 트리 접기
- 10.10.3 접기 연산 구현 선택하기
- 10.11 트리 매핑하기
- 10.12 균형 트리 다루기
- 10.12.1 트리 회전시키기
- 10.12.2 데이-스타우트-워런 알고리즘 사용하기
- 10.12.3 자동 균형 트리
- 10.13 요약
- 11장 고급 트리를 활용해 문제 해결하기
- 11.1 자체 균형 트리의 스택 안전성 및 성능 높이기
- 11.1.1 기본 레드-블랙 트리 구조 이해하기
- 11.1.2 레드-블랙 트리에 원소 추가하기
- 11.1.3 레드-블랙 트리에서 원소 삭제하기
- 11.2 레드-블랙 트리의 활용: 맵
- 11.2.1 맵 구현하기
- 11.2.2 맵 확장하기
- 11.2.3 비교 불가능한 키를 사용하는 Map 다루기
- 11.3 함수형 우선순위 큐 구현하기
- 11.3.1 우선순위 큐 접근 규약 살펴보기
- 11.3.2 우선순위 큐 용례 살펴보기
- 11.3.3 구현 요구 사항 살펴보기
- 11.3.4 레프티스트 힙 데이터 구조
- 11.3.5 레프티스트 힙 구현하기
- 11.3.6 큐와 유사한 인터페이스 구현하기
- 11.4 원소와 정렬한 리스트
- 11.5 비교 불가능한 원소에 대한 우선순위 큐
- 11.6 요약
- 12장 함수형 입출력
- 12.1 부수 효과를 컨텍스트 안에 가둔다는 것은 무슨 뜻인가
- 12.1.1 효과 처리하기
- 12.1.2 효과 구현하기
- 12.2 데이터 읽기
- 12.2.1 콘솔에서 데이터 읽기
- 12.2.2 파일 읽기
- 12.3 입력 테스트하기
- 12.4 완전히 함수형인 입출력
- 12.4.1 입출력을 완전히 함수형으로 만들기
- 12.4.2 순수 함수형 I/O 구현하기
- 12.4.3 I/O 조합하기
- 12.4.4 IO로 입력 다루기
- 12.4.5 IO 타입 확장하기
- 12.4.6 IO 타입을 스택 안전하게 만들기
- 12.5 요약
- 13장 액터로 상태 변이 공유하기
- 13.1 액터 모델
- 13.1.1 비동기 메시징 이해하기
- 13.1.2 병렬화 처리하기
- 13.1.3 액터 상태 변이 처리하기
- 13.2 액터 프레임워크 구현하기
- 13.2.1 한계 이해하기
- 13.2.2 액터 프레임워크 인터페이스 설계하기
- 13.3 AbstractActor 구현
- 13.4 액터가 행동하게 만들기
- 13.4.1 탁구 예제 구현하기
- 13.4.2 계산을 병렬로 수행하기
- 13.4.3 결과 순서 변경하기
- 13.4.4 성능 최적화하기
- 13.5 요약
- 14장 자주 일어나는 문제를 함수형으로 해결하기
- 14.1 단언문과 데이터 검증
- 14.2 함수와 효과 재시도하기
- 14.3 파일에서 프로퍼티 읽기
- 14.3.1 프로퍼티 파일 읽기
- 14.3.2 프로퍼티를 문자열로 읽기
- 14.3.3 더 나은 오류 메시지 만들기
- 14.3.4 프로퍼티를 리스트로 읽기
- 14.3.5 이넘(enum) 값 읽기
- 14.3.6 임의의 타입으로 된 프로퍼티 읽기
- 14.4 명령형 프로그램 변환하기: XML 리더
- 14.4.1 1단계: 명령형 해법
- 14.4.2 2단계: 명령형 프로그램을 좀 더 함수형으로 만들기
- 14.4.3 3단계: 프로그램을 더욱더 함수형으로 만들기
- 14.4.4 4단계: 인자 타입 문제 해결하기
- 14.4.5 5단계: 원소 처리 함수를 파라미터로 만들기
- 14.4.6 6단계: 엘리먼트 이름의 오류 처리하기
- 14.4.7 7단계: 예전 명령형 코드를 추가로 개선하는 방법
- 14.5 요약
- 부록 A 코틀린과 자바 함께 쓰기
- A.1 혼합 프로젝트를 만들고 관리하기
- A.1.1 그레이들로 간단한 프로젝트 만들기
- A.1.2 그레이들 프로젝트를 인텔리J로 임포트하기
- A.1.3 프로젝트에 의존 관계 추가하기
- A.1.4 멀티 모듈 프로젝트 만들기
- A.1.5 멀티 모듈 프로젝트에 의존 관계 추가하기
- A.2 자바 라이브러리 메서드와 코틀린 코드
- A.2.1 자바 원시 타입 사용하기
- A.2.2 자바 수 객체 타입 사용하기
- A.2.3 널 값 빠르게 실패시키기
- A.2.4 코틀린과 자바 문자열 타입 사용하기
- A.2.5 다른 타입 변환 구현하기
- A.2.6 자바 varargs 사용하기
- A.2.7 자바에서 널 가능성 지정하기
- A.2.8 게터와 세터 호출하기
- A.2.9 예약어로 된 자바 프로퍼티에 접근하기
- A.2.10 검사 예외 호출하기
- A.3 SAM 인터페이스
- A.4 코틀린 함수와 자바 코드
- A.4.1 코틀린 프로퍼티 변환하기
- A.4.2 코틀린 공개 필드 사용하기
- A.4.3 정적 필드
- A.4.4 코틀린 함수를 자바 메서드인 것처럼 호출하기
- A.4.5 코틀린 타입을 자바 타입으로 변환하기
- A.4.6 함수 타입
- A.5 코틀린/자바 혼합 프로젝트에서만 발생하는 문제
- A.6 요약
- 부록 B 코틀린에서 속성 기반 테스트하기
- B.1 속성 기반 테스트를 사용해야 하는 이유는 무엇인가
- B.1.1 인터페이스 작성하기
- B.1.2 테스트 작성하기
- B.2 속성 기반 테스트는 무엇인가
- B.3 추상화와 속성 기반 테스트
- B.4 속성 기반 단위 테스트의 의존 관계
- B.5 속성 기반 테스트 작성하기
- B.5.1 커스텀 생성기 작성하기
- B.5.2 커스텀 생성기 사용하기
- B.5.3 추상화를 더 진행해서 코드를 간단하게 만들기
- B.6 요약