F# 이란 무엇인가요?

F# 이란 무엇인가요?

F# 은 간결하고(succinct) 견고하며(robust) 성능 좋은 코드를 쓰기 위한 범용 프로그래밍 언어예요.

F# 을 쓰면 군더더기 없고 자기 스스로 설명이 되는 코드를 작성할 수 있죠. 프로그래밍의 세부적인 지식보다는, 여러분이 풀고 싶은 문제 영역(problem domain) 에 집중할 수 있게 해 줘요.

그런데도 속도와 호환성을 희생하지 않아요. F# 은 오픈소스이고, 크로스 플랫폼이며, 다른 언어와도 잘 섞어 쓸 수 있어요(interoperable).

출처: What is F# | Microsoft Learn

open System // Gets access to functionality in System namespace.

// Defines a list of names
let names = [ "Peter"; "Julia"; "Xi" ]

// Defines a function that takes a name and produces a greeting.
let getGreeting name = $"Hello, {name}"

// Prints a greeting for each name!
names
|> List.map getGreeting
|> List.iter (fun greeting -> printfn $"{greeting}! Enjoy your F#")

본문

F# 은 다양한 기능을 갖추고 있어요:

  • 가벼운 문법 (lightweight syntax)
  • 기본값이 불변(immutable by default)
  • 타입 추론과 자동 일반화 (type inference and automatic generalization)
  • 일급 함수 (first-class functions)
  • 강력한 데이터 타입
  • 패턴 매칭 (pattern matching)
  • 비동기 프로그래밍 (async programming)

이 모든 기능의 전체 목록은 F# language guide 문서에 정리되어 있어요.

풍부한 데이터 타입 (Rich data types)

Records 같은 타입이나 Discriminated Unions 을 쓰면 여러분의 데이터를 그대로 표현할 수 있어요.

// Group data with Records
type SuccessfulWithdrawal =
    { Amount: decimal
      Balance: decimal }

type FailedWithdrawal =
    { Amount: decimal
      Balance: decimal
      IsOverdraft: bool }

// Use discriminated unions to represent data of 1 or more forms
type WithdrawalResult =
    | Success of SuccessfulWithdrawal
    | InsufficientFunds of FailedWithdrawal
    | CardExpired of System.DateTime
    | UndisclosedFailure

F# 의 record 와 discriminated union 은 기본적으로 null 이 아니고, 불변이며, 비교 가능해요. 그래서 아주 쓰기 편해요.

함수와 패턴 매칭으로 얻는 정확성 (Correctness with functions and pattern matching)

F# 함수는 정의하기 쉬워요. 패턴 매칭 과 함께 쓰면, 컴파일러가 정확성을 강제해 주는 방식으로 동작을 정의할 수 있어요.

// Returns a WithdrawalResult
let withdrawMoney amount = // Implementation elided

let handleWithdrawal amount =
    let w = withdrawMoney amount

    // The F# compiler enforces accounting for each case!
    match w with
    | Success s -> printfn $"Successfully withdrew %f{s.Amount}"
    | InsufficientFunds f -> printfn $"Failed: balance is %f{f.Balance}"
    | CardExpired d -> printfn $"Failed: card expired on {d}"
    | UndisclosedFailure -> printfn "Failed: unknown :("

F# 함수는 일급(first-class)이기도 해요. 즉 다른 함수의 인자로 넘기거나, 다른 함수의 반환값으로 돌려줄 수 있어요.

객체를 다루는 연산을 정의하는 함수 (Functions to define operations on objects)

F# 은 객체(object)를 완전히 지원해요. 데이터와 기능을 섞어 써야 할 때 특히 유용하죠. 객체를 다루는 F# 멤버(member)와 함수를 정의할 수 있어요.

type Set<'T when 'T: comparison>(elements: seq<'T>) =
    member s.IsEmpty = // Implementation elided
    member s.Contains (value) =// Implementation elided
    member s.Add (value) = // Implementation elided
    // ...
    // Further Implementation elided
    // ...
    interface IEnumerable<'T>
    interface IReadOnlyCollection<'T>

module Set =
    let isEmpty (set: Set<'T>) = set.IsEmpty

    let contains element (set: Set<'T>) = set.Contains(element)

    let add value (set: Set<'T>) = set.Add(value)

F# 에서는 함수가 다루기 위한 일종의 타입으로 객체를 취급하는 코드를 자주 볼 수 있어요. generic interfaces, object expressions, 그리고 members 를 알맞게 사용하는 일은 규모가 큰 F# 프로그램에서 흔한 패턴이에요.

더 알아보기

더 넓은 F# 기능을 살펴보고 싶다면 F# Tour 문서도 확인해 보세요. F# 의 더 많은 기능을 천천히 소개해 줘요.