매개 변수 및 인수(F#)

업데이트: 2011년 4월

이 항목에서는 매개 변수를 정의하고 함수, 메서드 및 속성에 인수를 전달하기 위한 언어 지원에 대해 설명합니다. 여기서는 매개 변수를 참조로 전달하는 방법과 때마다 인수의 개수가 달라질 수 있는 메서드를 정의하고 사용하는 방법도 설명합니다.

매개 변수 및 인수

매개 변수라는 용어는 제공되어야 할 값의 이름을 설명하는 데 사용됩니다. 인수라는 용어는 각 매개 변수에 대해 제공되는 값을 나타냅니다.

매개 변수는 튜플 또는 변환 형식으로 지정하거나 이 둘의 몇 가지 조합으로 지정할 수 있습니다. 명시적 매개 변수 이름을 사용하여 인수를 전달할 수 있습니다. 메서드의 매개 변수는 선택적 요소로 지정하거나 기본값을 제공할 수 있습니다.

매개 변수 패턴

함수와 메서드에 제공되는 매개 변수는 일반적으로 공백을 사용하여 구분되는 패턴입니다. 즉, 원칙적으로 일치 식(F#)에서 설명하는 임의의 패턴을 함수 또는 메서드의 매개 변수 목록에 사용할 수 있습니다.

메서드의 인수 전달에는 일반적으로 튜플 형식이 사용됩니다. 튜플 형식은 .NET 메서드에서 인수가 전달되는 방식에 일치하므로 이와 같이 튜플 형식을 사용하면 다른 .NET 언어의 관점에서 볼 때 더 명확한 결과를 얻을 수 있습니다.

변환 형식은 대부분의 경우 let 바인딩을 사용하여 만든 함수에 사용됩니다.

다음 의사 코드에서는 튜플 및 커리된 인수의 예를 보여 줍니다.

// Tuple form.
member this.SomeMethod(param1, param2) = ...
// Curried form.
let function1 param1 param2 = ...

인수 중 일부는 튜플에 포함되고 다른 일부는 포함되지 않은 경우 조합된 형식을 사용할 수 있습니다.

let function2 param1 (param2a, param2b) param3 = ...

변환 함수를 사용하는 데 대한 자세한 내용은 인수 부분 적용을 참조하십시오.

매개 변수 목록에 다른 패턴을 사용할 수도 있지만 모든 가능한 입력에 매개 변수 패턴이 일치하지 않으면 런타임에 완전한 일치가 이루어지지 않을 수 있습니다. 매개 변수 목록에 지정된 패턴에 인수의 값이 일치하지 않으면 MatchFailureException 예외가 발생합니다. 매개 변수 패턴에 의해 불완전한 일치가 나타나면 컴파일러에서 경고가 발생합니다. 이러한 문제와 관련하여 매개 변수 목록에 자주 사용되는 패턴으로 와일드카드 패턴이 있습니다. 제공되는 모든 인수를 간단히 무시하고 싶은 경우 매개 변수 목록에 와일드카드 패턴을 사용합니다. 다음 코드에서는 인수 목록에 와일드카드 패턴을 사용하는 방법을 보여 줍니다.

let makeList _ = [ for i in 1 .. 100 -> i * i ]
// The arguments 100 and 200 are ignored.
let list1 = makeList 100
let list2 = makeList 200

다음 코드에서와 같이 대개 문자열 배열로 제공되는 명령줄 인수가 필요하지 않거나 프로그램의 주 진입점에 전달되는 인수 같이 전달된 인수가 필요하지 않은 경우에 와일드카드 패턴이 유용할 수 있습니다.

[<EntryPoint>]
let main _ =
    printfn "Entry point!"
    0

인수에 자주 사용되는 다른 패턴으로는 as 패턴과 구별된 공용 구조체에 관련된 식별자 패턴 및 활성 패턴이 있습니다. 다음과 같이 단일 사례의 구별된 공용 구조체 패턴을 사용할 수 있습니다.

type Slice = Slice of int * int * string

let GetSubstring1 (Slice(p0, p1, text)) = 
    printfn "Data begins at %d and ends at %d in string %s" p0 p1 text
    text.[p0..p1]

let substring = GetSubstring1 (Slice(0, 4, "Et tu, Brute?"))
printfn "Substring: %s" substring

출력은 다음과 같습니다.

Data begins at 0 and ends at 4 in string Et tu, Brute?
Et tu

다음 코드 줄에 나와 있는 것과 같이 as 패턴을 사용하여 일치하는 값을 로컬 값으로 저장할 수 있습니다.

let GetSubstring2 (Slice(p0, p1, text) as s) = s

그 밖에 자주 사용되는 패턴으로는 암시적 인수에 대한 패턴 일치를 즉시 수행하는 람다 식을 함수 본문으로 제공하여 명명되지 않은 마지막 인수를 남기는 함수가 있습니다. 다음 코드 줄에서는 이와 관련된 예를 보여 줍니다.

let isNil = function [] -> true | _::_ -> false

이 코드에서는 제네릭 목록을 취한 다음 목록이 비어 있으면 true를 반환하고 그렇지 않으면 false를 반환하는 함수를 정의합니다. 이와 같은 기술을 사용하면 코드를 읽고 이해하기가 더 어려워질 수 있습니다.

때로는 불완전한 일치와 관련된 패턴이 유용하게 사용될 수도 있습니다. 예를 들어 프로그램의 목록에 요소가 세 개뿐이라는 사실을 알고 있는 경우 매개 변수 목록에 다음과 같은 패턴을 사용할 수도 있습니다.

let sum [a; b; c;] = a + b + c

불완전한 일치와 관련된 패턴은 프로토타입을 신속하게 작성해야 하거나 기타 목적을 위해 임시로 필요한 경우에만 사용하는 것이 좋습니다. 컴파일러는 다음 코드에 대해 경고를 생성합니다. 이와 같은 패턴은 모든 가능한 입력의 일반적인 사례를 모두 처리할 수 없으므로 구성 요소 API에는 적합하지 않습니다.

명명된 인수

메서드의 인수는 쉼표로 구분된 인수 목록에서 차지하는 위치로 지정할 수도 있고 이름을 제공하여 메서드에 명시적으로 전달할 수도 있습니다. 인수를 명시적으로 전달하는 경우에는 이름 뒤에 등호와 전달할 값을 추가해야 합니다. 이름을 제공하여 인수를 지정하는 경우 인수의 표시 순서가 선언에 사용된 순서와 달라도 됩니다.

명명된 인수를 사용하면 코드를 더 쉽게 읽을 수 있고 메서드 매개 변수의 순서를 바꾸는 경우 등과 같이 API를 특정 방식으로 변경할 때 그 변경 내용에 코드를 더 쉽게 맞출 수 있습니다.

명명된 인수는 메서드에만 사용할 수 있으며 let 바인딩된 함수, 함수 값 또는 람다 식에는 사용할 수 없습니다.

다음 코드 예제에서는 명명된 인수를 사용하는 방법을 보여 줍니다.

type SpeedingTicket() =
    member this.GetMPHOver(speed: int, limit: int) = speed - limit

let CalculateFine (ticket : SpeedingTicket) =
    let delta = ticket.GetMPHOver(limit = 55, speed = 70)
    if delta < 20 then 50.0 else 100.0

let ticket1 : SpeedingTicket = SpeedingTicket()
printfn "%f" (CalculateFine ticket1)

클래스 생성자에 대한 호출에서 명명된 매개 변수와 비슷한 구문을 사용하여 클래스의 속성 값을 설정할 수 있습니다. 다음 예에서는 이 구문을 보여 줍니다.

 type Account() =
    let mutable balance = 0.0
    let mutable number = 0
    let mutable firstName = ""
    let mutable lastName = ""
    member this.AccountNumber
       with get() = number
       and set(value) = number <- value
    member this.FirstName
       with get() = firstName
       and set(value) = firstName <- value
    member this.LastName
       with get() = lastName
       and set(value) = lastName <- value
    member this.Balance
       with get() = balance
       and set(value) = balance <- value
    member this.Deposit(amount: float) = this.Balance <- this.Balance + amount
    member this.Withdraw(amount: float) = this.Balance <- this.Balance - amount


let account1 = new Account(AccountNumber=8782108, 
                           FirstName="Darren", LastName="Parker",
                           Balance=1543.33)

자세한 내용은 생성자(F#)를 참조하십시오.

선택적 매개 변수

매개 변수 이름 앞에 물음표를 사용하여 메서드에 대한 선택적 매개 변수를 지정할 수 있습니다. 선택적 매개 변수는 F# 옵션 형식으로 해석되므로 옵션 형식을 쿼리하는 일반적인 방법, 즉 match 식에 Some 및 None을 사용하여 해당 매개 변수를 쿼리할 수 있습니다. 선택적 매개 변수는 멤버에 대해서만 허용되며 let 바인딩을 사용하여 만든 함수에는 허용되지 않습니다.

선택적 인수의 기본값을 설정하는 defaultArg 함수를 사용할 수도 있습니다. defaultArg 함수는 선택적 매개 변수를 첫째 인수로 취하고 기본값을 둘째 인수로 취합니다.

다음 예제에서는 선택적 매개 변수를 사용하는 방법을 보여 줍니다.

type DuplexType =
    | Full
    | Half

type Connection(?rate0 : int, ?duplex0 : DuplexType, ?parity0 : bool) =
    let duplex = defaultArg duplex0 Full
    let parity = defaultArg parity0 false
    let mutable rate = match rate0 with
                        | Some rate1 -> rate1
                        | None -> match duplex with
                                  | Full -> 9600
                                  | Half -> 4800
    do printfn "Baud Rate: %d Duplex: %A Parity: %b" rate duplex parity

let conn1 = Connection(duplex0 = Full)
let conn2 = Connection(duplex0 = Half)
let conn3 = Connection(300, Half, true)

출력은 다음과 같습니다.

Baud Rate: 9600 Duplex: Full Parity: false
Baud Rate: 4800 Duplex: Half Parity: false
Baud Rate: 300 Duplex: Half Parity: true

참조로 전달

F#에서는 매개 변수를 참조로 전달하도록 지정하는 byref 키워드를 지원합니다. 이와 같이 매개 변수를 참조로 전달하면 함수를 실행한 후에도 값의 변경 내용이 모두 유지됩니다. byref 매개 변수에 제공되는 값은 변경할 수 있는 값이어야 합니다. 또는 적절한 형식의 참조 셀을 전달할 수 있습니다.

.NET 언어에서는 매개 변수를 참조로 전달하는 방법에 기초하여 함수에서 여러 개의 값을 반환할 수 있습니다. F#에서는 이와 같은 목적으로 튜플을 반환하거나 변경 가능한 참조 셀을 매개 변수로 사용할 수 있습니다. byref 매개 변수는 주로 .NET 라이브러리와의 상호 운용성을 위해 필요합니다.

다음 예제에서는 byref 키워드를 사용하는 방법을 보여 줍니다. 참조 셀을 매개 변수로 사용할 때는 다음 코드의 Increment에 대한 첫 번째 호출에 나와 있는 것과 같이 단순히 ref 연산자만 추가해서 되는 것이 아니라 참조 셀을 명명된 값으로 만들고 이를 매개 변수로 사용해야 합니다. 참조 셀을 만들면 내부 값의 복사본이 만들어지므로 첫 번째 호출에서는 단지 임시 값이 증가할 뿐입니다.

type Incrementor(z) =
    member this.Increment(i : int byref) =
       i <- i + z

let incrementor = new Incrementor(1)
let mutable x = 10
// Not recommended: Does not actually increment the variable.
incrementor.Increment(ref x)
// Prints 10.
printfn "%d" x  

let mutable y = 10
incrementor.Increment(&y)
// Prints 11.
printfn "%d" y 

let refInt = ref 10
incrementor.Increment(refInt)
// Prints 11.
printfn "%d" !refInt  

튜플을 반환 값으로 사용하여 .NET 라이브러리 메서드에 임의의 out 매개 변수를 저장할 수 있습니다. 또는 out 매개 변수를 byref 매개 변수로 취급할 수 있습니다. 다음 코드 예제에서는 이 두 가지 방법을 모두 보여 줍니다.

// TryParse has a second parameter that is an out parameter
// of type System.DateTime.
let (b, dt) = System.DateTime.TryParse("12-20-04 12:21:00")

printfn "%b %A" b dt

// The same call, using an address of operator.
let mutable dt2 = System.DateTime.Now
let b2 = System.DateTime.TryParse("12-20-04 12:21:00", &dt2)

printfn "%b %A" b2 dt2

매개 변수 배열

때로는 형식이 각기 다른 매개 변수를 임의의 개수만큼 취하는 함수를 정의해야 할 수도 있습니다. 사용할 수 있는 모든 형식을 설명하는 모든 가능한 경우의 오버로드된 메서드를 만든다는 것은 사실상 불가능한 일입니다. .NET 플랫폼에서는 매개 변수 배열 기능을 통해 그와 같은 메서드를 지원합니다. 해당 시그니처에 매개 변수 배열을 취하는 메서드에 대해 임의 개수의 매개 변수를 제공할 수 있습니다. 매개 변수는 배열에 추가됩니다. 배열 요소의 형식에 따라 함수에 전달할 수 있는 매개 변수 형식이 결정됩니다. Object를 요소 형식으로 사용하여 매개 변수 배열을 정의하면 클라이언트 코드에서 값을 그 형식에 상관없이 전달할 수 있습니다.

F#의 경우 매개 변수 배열은 메서드에서만 정의할 수 있습니다. 독립 실행형 함수나 모듈에 정의된 함수에는 매개 변수 배열을 사용할 수 없습니다.

매개 변수 배열을 정의하는 데는 ParamArray 특성을 사용합니다. ParamArray 특성은 마지막 매개 변수에만 적용할 수 있습니다.

다음 코드에서는 매개 변수 배열을 취하는 .NET 메서드를 호출하는 방법과 F#에서 매개 변수 배열을 취하는 메서드가 있는 형식을 정의하는 방법을 보여 줍니다.

open System

type X() =
    member this.F([<ParamArray>] args: Object[]) =
        for arg in args do
            printfn "%A" arg

[<EntryPoint>]
let main _ =
    // call a .NET method that takes a parameter array, passing values of various types
    Console.WriteLine("a {0} {1} {2} {3} {4}", 1, 10.0, "Hello world", 1u, true)

    let xobj = new X()
    // call an F# method that takes a parameter array, passing values of various types
    xobj.F("a", 1, 10.0, "Hello world", 1u, true)
    0

프로젝트에서 실행될 때 이전 코드의 출력은 다음과 같습니다.

a 1 10 Hello world 1 True
"a"
1
10.0
"Hello world"
1u
true

참고 항목

개념

멤버(F#)

변경 기록

날짜

변경 내용

이유

2011년 4월

생성자에서 속성 값 설정을 설명하는 단원이 추가되었습니다.

콘텐츠 버그 수정