본격적으로 F#을 시작해봅시다.
먼저 F#은 닷넷 위에서 돌아가는 언어이기 때문에 닷넷 개발환경을 갖추시면 그게 곧 F#의 개발환경이 됩니다. 보통은 Visual Studio겠지만 Rider 혹은 VSCode 등의 텍스트 에디터를 사용하셔도 됩니다. 이도저도 다 귀찮다면 Try F#에서 온라인으로 실행시켜 볼 수 있습니다.
let
Binding
F#은 함수형 언어입니다. 이 말은 모든 것을 함수로 취급하고 관리한다는 의미입니다. 따라서 엄밀히 말해서 함수형 언어에서는 변수라는 개념이 존재하지 않습니다.
F#에서 함수를 선언할 때는 let
을 사용합니다.
let square x = x * x // square(x) = x * x
let result = square 3 // 9
let a = 3 // 3
첫번째 줄의 square
는 인자 1개를 x
라는 이름으로 받아 x * x
를 리턴하는 함수입니다.
두번째 줄의 result
는 인자를 받지 않고 square 3
을 리턴하는 함수입니다.
세번째 줄의 a
는 인자를 받지 않고 3
을 리턴하는 함수입니다.
square
는 누가 봐도 함수라고 생각하겠지만, result
와 a
는 변수가 아닌가? 라는 생각이 드실 겁니다. 하지만 이들 또한 인자가 없고 해당 값을 리턴하는 함수로 봐야 함수형 언어를 쉽게 이해할 수 있습니다.
또한 모든 것이 함수로 취급되기 때문에, 함수 뒤에 별다른 연산식 없이 값만 나열된 것은 자연히 그 함수의 인자로 취급됩니다. 그 때문에 인자를 굳이 ()
로 감쌀 필요가 없죠. 물론 우선순위를 바꿔야 할 필요가 있다면 괄호를 써도 상관없습니다.
let temp = square (a + 3) // 36
이 코드에서는 a + 3
을 먼저 계산한 뒤 그 값인 6
을 square
함수에 넘겨줍니다.
저번 글에서 잠깐 언급했지만, F#을 비롯한 함수형 언어에서는 기본적으로 모든 함수가 immutable입니다.
만일 이미 기존에 존재한 함수에 새 값을 할당하고자 할 경우, 아예 새 메모리를 할당하여 그 값을 바인딩합니다.
이 과정에서 기존에 정의된 값은 가려지기 때문에 다시는 접근이 불가능합니다.
하지만 F#은 순수한 FP 언어가 아니기 때문에 함수를 mutable하게 만들 수 있는 키워드를 제공합니다.
let mutable mutableVar = 2
mutableVar <- mutableVar + 1 // 3
mutable한 함수를 선언하고자 한다면, let mutable
을 사용하면 됩니다. 이렇게 만들어진 mutable 함수는 <-
를 사용해서 값을 변경할 수 있습니다. (=
는 let
으로 바인딩할 때를 제외하면 값이 같은지를 확인하는 함수이므로 여기서 =
를 사용해서는 안 됩니다.)
mutable은 그 자체로 FP의 패러다임을 깨기 때문에 사용을 신중하게 고려해야 합니다. 대부분의 상황에서는 mutable 없이도 충분히 구현이 가능합니다.
Primitive Types
위에서 정의한 square
함수를 보면 인자 x
에 딱히 타입을 정해두지 않은 것을 알 수 있습니다. 하지만 이것이 F#에선 타입이 존재하지 않는다는 것을 의미하진 않습니다. F#은 컴파일 시에 type이 결정되는 Statically Typed Language이며, 강력한 타입 추론을 지원합니다. F#에서 지원하는 primitive type은 다음과 같으며 unit
을 제외하고 전부 .NET에서의 type에 대응됩니다.
(좌측이 F# type, 우측이 .NET type입니다.)
- bool = Bool
- byte = Byte
- sbyte = SByte
- int16 = Int16
- uint16 = UInt16
- int = Int32
- uint = UInt32
- int64 = Int64
- uint64 = UInt64
- nativeint = IntPtr
- unativeint = UIntPtr
- decimal = Decimal
- float, double = Double
- float32, single = Single
- char = Char
- string = String
- unit : '값이 없음'을 나타내는 F#만의 타입입니다.
C#에서는 float
과 double
이 다르지만, F#에서는 둘 다 동일한 type, 정확히는 double
로 취급됩니다.
또한 C#에서 사용하는 대부분의 연산자 역시 F#에서 동일하게 사용 가능합니다.
let boolean1 = true
let boolean2 = false
let boolean3 = not boolean1 && (boolean2 || false) // false
let string1 = "Hello"
let string2 = "world"
let string3 = @"C:\Program Files\" // @은 F#에서도 verbatim을 뜻합니다.
let string4 = """Triple quote "string" literal""" // Triple quote도 가능합니다.
let string5 = string1 + " " + string2 // "Hello world"
let string6 = string5.[0..6] // Substring - "Hello w"
위에서도 언급했듯이 F#은 타입 추론을 하기 때문에 명시적으로 지정해줄 필요는 없지만, 필요하다면 지정하는 것도 가능합니다.
let sampleFunc (x:Int) : Int = square x - x + 1
다음 글에선 Tuple에 대해 알아보겠습니다.
Top comments (0)