F#의 값

F#의 값 (Values)

F#에서 값(values)은 특정 타입을 가진 하나의 양(quantity)이에요. 정수나 부동 소수점 숫자, 문자나 텍스트, 리스트, 시퀀스, 배열, 튜플, 구별된 공용체(discriminated union), 레코드, 클래스 타입, 함수 값까지 — 값이 될 수 있는 대상이 정말 다양하죠. 이 글에서는 값이 어떤 식으로 묶이고(binding), 왜 불변(immutable)이 권장되는지, 그리고 꼭 필요할 때 값을 바꾸는 방법까지 차근차근 짚어볼게요.

출처

본문

값 묶기 (Binding a Value)

binding이라는 단어는 '이름을 정의에 연결한다'는 뜻이에요. F#에서는 let 키워드가 값을 묶는 역할을 해요. 예를 들면 이렇죠.

let a = 1
let b = 100u
let str = "text"

// A function value binding.

let f x = x + 1

값의 타입은 정의에서 추론돼요. 정수나 부동 소수점 숫자 같은 기본 타입의 경우에는 그 리터럴(literal)의 타입에서 결정돼요. 그래서 위 예시에서 컴파일러는 aint로, bunsigned int로 추론해요. 함수 값의 타입은 함수 본문의 반환 값에서 정해져요. 함수 값 타입에 대한 자세한 내용은 Functions를, 리터럴 타입은 Literals를 참고하면 돼요.

한 가지 알아둘 점이 있어요. 기본적으로 컴파일러는 쓰이지 않는 바인딩에 대해 진단 메시지를 내보내지 않아요. 그 메시지를 받고 싶다면 프로젝트 파일에서 warning 1182를 켜거나, 컴파일러를 호출할 때 켜면 돼요 (Compiler Options--warnon 항목을 참고하세요).

왜 불변인가? (Why Immutable?)

불변 값(immutable value)은 프로그램이 실행되는 동안 절대 바뀌지 않는 값이에요. C++, Visual Basic, C# 같은 언어에 익숙하다면, F#이 실행 중 새 값을 할당할 수 있는 변수보다 불변 값을 우선시한다는 게 조금 낯설 수도 있어요. 하지만 불변 데이터는 함수형 프로그래밍의 핵심 요소거든요.

멀티스레드 환경에서는 여러 스레드가 맘대로 바꿀 수 있는 공유 가변 변수를 관리하기가 무척 어려워요. 게다가 가변 변수는 어떤 변수를 다른 함수에 넘겼을 때 그 값이 바뀔 수도 있는지 판단하기 힘든 경우가 많아요.

순수 함수형 언어에는 변수라는 개념 자체가 없고, 함수는 수학적 함수처럼 엄격하게 동작해요. 절차적 언어에서 변수 할당으로 값을 바꾸는 코드는, 함수형 언어에서는 '입력인 불변 값, 불변 함수, 그리고 출력인 서로 다른 불변 값'으로 표현돼요. 이렇게 수학적으로 엄격할수록 프로그램이 어떻게 동작할지 더 치밀하게 추론할 수 있어요. 추론이 정밀해지면 컴파일러가 코드를 더 꼼꼼히 검사하고 더 효과적으로 최적화할 수 있고, 개발자가 올바른 코드를 이해하고 작성하는 일도 쉬워져요. 그래서 함수형 코드는 일반적인 절차적 코드보다 디버깅하기 쉬운 편이에요.

F#은 엄밀히 말하면 순수 함수형 언어는 아니지만, 함수형 프로그래밍을 완전히 지원해요. 불변 값을 쓰는 건 좋은 습관인데, 그래야 함수형 프로그래밍이 주는 중요한 이점을 코드에 그대로 살릴 수 있기 때문이에요.

가변 변수 (Mutable Variables)

mutable 키워드를 쓰면 바꿀 수 있는 변수를 지정할 수 있어요. F#의 가변 변수는 일반적으로 타입의 필드나 지역 값처럼 범위를 제한해서 쓰는 게 좋아요. 범위가 좁은 가변 변수는 통제하기 쉽고, 잘못된 방식으로 수정될 가능성도 낮아요.

가변 변수에 초깃값을 지정할 때는 값 하나 정의하듯 let 키워드를 똑같이 쓰면 돼요. 차이점은 이후에 <- 연산자로 새 값을 계속 할당할 수 있다는 점이에요. 예를 들어볼게요.

let mutable x = 1
x <- x + 1

한 가지 짚고 넘어갈 게 있어요. 클로저(closure)에 포착되면 mutable로 표시된 값은 자동으로 'a ref로 승격될 수 있어요. 여기에는 seq 빌더처럼 클로저를 만드는 형태도 포함돼요. 이런 승격이 일어날 때 알림을 받고 싶다면 프로젝트 파일에서 warning 3180을 켜거나 컴파일러를 호출할 때 켜면 돼요.

더 알아보기

제목 설명
let Bindings let 키워드로 이름을 값과 함수에 묶는 방법을 다뤄요.
Functions F# 함수에 대한 전반적인 개요를 제공해요.

함께 읽어볼 만한 자료: