매개 변수 및 인수
이 항목에서는 매개 변수를 정의하고 함수, 메서드 및 속성에 인수를 전달하는 언어 지원에 대해 설명합니다. 참조를 통해 전달하는 방법 및 다양한 수의 인수를 사용할 수 있는 메서드를 정의하고 사용하는 방법에 대한 정보가 포함됩니다.
매개 변수 및 인수
용어 매개 변수는 제공될 것으로 예상되는 값의 이름을 설명하는 데 사용됩니다. 용어 인수는 각 매개 변수에 제공된 값에 사용됩니다.
매개 변수는 튜플 또는 커리 형식으로 또는 둘의 일부 조합으로 지정할 수 있습니다. 명시적 매개 변수 이름을 사용하여 인수를 전달할 수 있습니다. 메서드의 매개 변수는 선택 사항으로 지정하고 기본값을 지정할 수 있습니다.
매개 변수 패턴
함수 및 메서드에 제공되는 매개 변수는 일반적으로 공백으로 구분된 패턴입니다. 즉, 일치 식에서 설명된 모든 패턴을 함수 또는 멤버의 매개 변수 목록에서 사용할 수 있습니다.
메서드는 일반적으로 인수 전달의 튜플 형식을 사용합니다. 이렇게 하면 튜플 형식이 .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
활성 패턴은 다음 예제와 같이 인수를 원하는 형식으로 변환할 때 매개 변수로 유용할 수 있습니다.
type Point = { x : float; y : float }
let (| Polar |) { x = x; y = y} =
( sqrt (x*x + y*y), System.Math.Atan (y/ x) )
let radius (Polar(r, _)) = r
let angle (Polar(_, theta)) = theta
다음 코드 줄과 같이 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#)를 참조하세요.
호출 속성 setter를 의미하는 동일한 기술은 모든 객체 반환 메서드에도 적용됩니다(예: 공장 메서드).
type Widget() =
member val Width = 1 with get,set
member val Height = 1 with get,set
type WidgetFactory =
static member MakeNewWidget() =
new Widget()
static member AdjustWidget(w: Widget) =
w
let w = WidgetFactory.MakeNewWidget(Width=10)
w.Width // = 10
w.Height // = 1
WidgetFactory.AdjustWidget(w, Height=10)
w.Height // = 10
이러한 멤버는 임의의 작업을 수행할 수 있으며 구문은 최종 값을 반환하기 전에 속성 setter를 호출하는 짧은 손입니다.
선택적 매개 변수
매개 변수 이름 앞에 물음표를 사용하여 메서드에 대한 선택적 매개 변수를 지정할 수 있습니다. 호출 수신자의 관점에서 선택적 매개 변수는 F# 옵션 형식으로 해석되므로 Some
및 None
을 사용한 match
식을 사용하여 옵션 형식을 정기적으로 쿼리할 수 있습니다. 선택적 매개 변수는 멤버에만 허용되며 let
바인딩을 사용하여 만든 함수에서는 허용되지 않습니다.
?arg=None
, ?arg=Some(3)
또는 ?arg=arg
같은 매개 변수 이름으로 메서드에 기존 선택적 값을 전달할 수 있습니다. 선택적 인수를 다른 메서드에 전달하는 메서드를 빌드할 때 유용할 수 있습니다.
선택적 인수의 기본값을 설정하는 함수 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)
let conn4 = Connection(?duplex0 = None)
let conn5 = Connection(?duplex0 = Some(Full))
let optionalDuplexValue : option<DuplexType> = Some(Half)
let conn6 = Connection(?duplex0 = optionalDuplexValue)
출력은 다음과 같습니다.
Baud Rate: 9600 Duplex: Full Parity: false
Baud Rate: 4800 Duplex: Half Parity: false
Baud Rate: 300 Duplex: Half Parity: true
Baud Rate: 9600 Duplex: Full Parity: false
Baud Rate: 9600 Duplex: Full Parity: false
Baud Rate: 4800 Duplex: Half Parity: false
C# 및 Visual Basic interop의 목적을 위해 F#에서 [<Optional; DefaultParameterValue<(...)>]
특성을 사용하면 호출자가 인수를 선택 사항으로 볼 수 있습니다. 이는 MyMethod(int i = 3)
에서 C#에서 인수를 선택 사항으로 정의하는 것과 같습니다.
open System
open System.Runtime.InteropServices
type C =
static member Foo([<Optional; DefaultParameterValue("Hello world")>] message) =
printfn $"{message}"
새 개체를 기본 매개 변수 값으로 지정할 수도 있습니다. 예를 들어 Foo
멤버는 선택적 CancellationToken
(을)를 입력으로 사용할 수 있습니다.
open System.Threading
open System.Runtime.InteropServices
type C =
static member Foo([<Optional; DefaultParameterValue(CancellationToken())>] ct: CancellationToken) =
printfn $"{ct}"
DefaultParameterValue
(으)로 인수가 지정된 값은 매개 변수의 형식과 일치해야 합니다. 예를 들어 다음은 허용되지 않습니다.
type C =
static member Wrong([<Optional; DefaultParameterValue("string")>] i:int) = ()
이 경우 컴파일러는 경고를 생성하고 두 특성을 모두 무시합니다. 그렇지 않으면 컴파일러가 잘못된 형식(예: [<Optional; DefaultParameterValue(null:obj)>] o:obj
)을 유추하므로 null
기본값은 형식 주석을 추가해야 합니다.
참조로 전달
참조로 F# 값을 전달하려면 관리되는 포인터 형식인 byrefs가 포함됩니다. 사용할 형식에 대한 지침은 다음과 같습니다.
- 포인터만 읽어야 하는 경우
inref<'T>
(을)를 사용합니다. - 포인터에만 쓸 필요가 있는 경우
outref<'T>
(을)를 사용합니다. - 포인터를 읽고 쓰려면
byref<'T>
(을)를 사용합니다.
let example1 (x: inref<int>) = printfn $"It's %d{x}"
let example2 (x: outref<int>) = x <- x + 1
let example3 (x: byref<int>) =
printfn $"It's %d{x}"
x <- x + 1
let test () =
// No need to make it mutable, since it's read-only
let x = 1
example1 &x
// Needs to be mutable, since we write to it
let mutable y = 2
example2 &y
example3 &y // Now 'y' is 3
매개 변수는 포인터이고 값은 변경 가능하므로 함수를 실행한 후에는 값에 대한 변경 내용이 유지됩니다.
튜플을 반환 값으로 사용하여 모든 out
매개 변수를 .NET 라이브러리 메서드에 저장할 수 있습니다. 또는 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 구현은 매개 변수 배열 기능을 통해 이러한 메서드를 지원합니다. 해당 서명에서 매개 변수 배열을 사용하는 메서드는 임의의 개수의 매개 변수와 함께 제공할 수 있습니다. 매개 변수는 배열에 배치됩니다. 배열 요소의 형식은 함수에 전달할 수 있는 매개 변수 형식을 결정합니다. System.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
참고 항목
.NET