DEV Community

CloudHolic
CloudHolic

Posted on • Originally published at dev.to

F# Tutorial (2) - Basics

본격적으로 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
Enter fullscreen mode Exit fullscreen mode

첫번째 줄의 square는 인자 1개를 x라는 이름으로 받아 x * x를 리턴하는 함수입니다.
두번째 줄의 result는 인자를 받지 않고 square 3을 리턴하는 함수입니다.
세번째 줄의 a는 인자를 받지 않고 3을 리턴하는 함수입니다.

square는 누가 봐도 함수라고 생각하겠지만, resulta는 변수가 아닌가? 라는 생각이 드실 겁니다. 하지만 이들 또한 인자가 없고 해당 값을 리턴하는 함수로 봐야 함수형 언어를 쉽게 이해할 수 있습니다.

또한 모든 것이 함수로 취급되기 때문에, 함수 뒤에 별다른 연산식 없이 값만 나열된 것은 자연히 그 함수의 인자로 취급됩니다. 그 때문에 인자를 굳이 ()로 감쌀 필요가 없죠. 물론 우선순위를 바꿔야 할 필요가 있다면 괄호를 써도 상관없습니다.

let temp = square (a + 3)   // 36
Enter fullscreen mode Exit fullscreen mode

이 코드에서는 a + 3을 먼저 계산한 뒤 그 값인 6square 함수에 넘겨줍니다.

저번 글에서 잠깐 언급했지만, F#을 비롯한 함수형 언어에서는 기본적으로 모든 함수가 immutable입니다.
만일 이미 기존에 존재한 함수에 새 값을 할당하고자 할 경우, 아예 새 메모리를 할당하여 그 값을 바인딩합니다.
이 과정에서 기존에 정의된 값은 가려지기 때문에 다시는 접근이 불가능합니다.

하지만 F#은 순수한 FP 언어가 아니기 때문에 함수를 mutable하게 만들 수 있는 키워드를 제공합니다.

let mutable mutableVar = 2
mutableVar <- mutableVar + 1    // 3
Enter fullscreen mode Exit fullscreen mode

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#에서는 floatdouble이 다르지만, 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"

Enter fullscreen mode Exit fullscreen mode

위에서도 언급했듯이 F#은 타입 추론을 하기 때문에 명시적으로 지정해줄 필요는 없지만, 필요하다면 지정하는 것도 가능합니다.

let sampleFunc (x:Int) : Int = square x - x + 1
Enter fullscreen mode Exit fullscreen mode

다음 글에선 Tuple에 대해 알아보겠습니다.

Top comments (0)