더북(TheBook)

여기서는 모든 연산이 첫 번째 리스트에만 수행됐고 그 때문에 당혹스러운 결과가 나왔다. 타입 추론으로 인해 (타입이 Boolean인) 연산 결과를 list2list3라는 두 참조에 대입할 때 아무런 타입 오류가 없었다. 코틀린은 이 두 참조를 자동으로 Boolean 타입으로 지정한다. 이런 이유로 되도록 타입을 명시하는 편이 좋다. 타입을 명시하면 다음과 같은 코드는 컴파일되지 않는다.

val list1: List<Int> = mutableListOf(1, 2, 3)
val list2: List<Int> = list1.add(1) // <-- 컴파일 오류
val list3: List<Int> = list1.addAll(list2) // <-- 컴파일 오류
println(list1)
println(list2)
println(list3)

+ 연산자는 plus라고 부르는 중위(infix) 확장 함수를 호출한다. 코틀린에서는 List를 확장하는 Collection 인터페이스 안에 plus 정의가 들어 있다. 확장 함수는 인자를 받아 새 리스트를 만드는 정적 함수로 컴파일된다. + 연산자를 가변 리스트에 사용할 수도 있지만, +를 사용하면 불변 리스트와 같은 결과를 돌려받게 되며, 원래의 가변 리스트는 변하지 않고 그대로 남는다.

불변성인 영속적 데이터 구조(persistent data structure)를 데이터 공유(data sharing)를 사용해 구현하는 방법을 이해하는 독자라면 코틀린의 불변 리스트가 데이터를 공유하지 않는다는 사실에 실망할지도 모른다. (코틀린 불변 리스트는 원소는 공유하지만, 리스트 데이터는 공유하지 않는다.) 코틀린 리스트에 원소를 추가하면 완전히 새로운 리스트를 만들어낸다. 5장에서 데이터를 공유하는 불변 리스트를 직접 작성하는 방법을 살펴본다. 데이터를 공유하면 메모리 공간을 절약하고 일부 연산의 경우 성능이 더 좋아질 수도 있다.

신간 소식 구독하기
뉴스레터에 가입하시고 이메일로 신간 소식을 받아 보세요.