불변 값
불변 값 (Immutable Values)
순수 함수형 프로그래밍(FP, Functional Programming)에서는 오직 불변(immutable) 값만 사용해요. Scala에서 이 말은 이렇게 풀어볼 수 있어요.
출처: Scala 3 Book
본문
- 모든 변수는
val필드로 만들어져요. List,Vector, 불변Map과Set같은 불변 컬렉션 클래스만 사용해요.
불변 변수만 쓴다면 재미있는 질문이 생겨요. 모든 게 불변이라면, 도대체 무엇이 어떻게 변하는 걸까요?
컬렉션을 다룰 때의 한 가지 답은 이거예요. 기존 컬렉션을 변형(mutate)하지 않는 대신, 기존 컬렉션에 함수를 적용해서 새로운 컬렉션을 만드는 거죠. 여기서 map이나 filter 같은 고차 함수가 등장해요.
예를 들어 전부 소문자인 이름들의 리스트, List[String]이 있다고 상상해 볼게요. 여기서 "j"로 시작하는 모든 이름을 찾고, 그 이름들을 대문자로 만들고 싶다고 해요. FP에서는 이렇게 코드를 써요.
val a = List("jane", "jon", "mary", "joe")
val b = a.filter(_.startsWith("j"))
.map(_.capitalize)
보시다시피 원래 리스트 a를 변형하지 않아요. 대신 a에 필터링과 변환 함수를 적용해 새 컬렉션을 만들고, 그 결과를 새 불변 변수 b에 할당하죠.
마찬가지로 FP에서는 가변 var 생성자 파라미터를 가진 클래스를 만들지 않아요. 즉, 이런 코드는 쓰지 않는답니다.
// don't do this in FP
class Person(var firstName: String, var lastName: String)
--- ---
대신, 생성자 파라미터가 기본적으로 val인 case class를 만드는 게 일반적이에요.
case class Person(firstName: String, lastName: String)
이제 Person 인스턴스를 val 필드로 만들어요.
val reginald = Person("Reginald", "Dwight")
그리고 데이터를 변경할 필요가 생기면, case class에 딸려 오는 copy 메서드를 사용해서 "복사하면서 데이터를 갱신"해요.
val elton = reginald.copy(
firstName = "Elton", // update the first name
lastName = "John" // update the last name
)
불변 컬렉션과 변수를 다루는 데는 다른 기법도 더 있어요. 다만 이 예제들만으로도 그 기법들의 맛을 보기엔 충분하죠.
필요에 따라 case class 대신 enum, trait, 또는 class를 만드는 경우도 있어요. 자세한 내용은 Data Modeling 챕터를 참고하세요.
더 알아보기
- "Data Modeling" 챕터 (Scala 3 Book)
- "What is Functional Programming?" 챕터 (Scala 3 Book)