パラメヌタヌず匕数

この蚘事では、パラメヌタヌを定矩し、関数、メ゜ッド、およびプロパティに匕数を枡すための蚀語サポヌトに぀いお説明したす。 これには、参照枡しの方法ず、可倉数の匕数を受け取るこずができるメ゜ッドを定矩しお䜿甚する方法に関する情報が含たれおいたす。

"パラメヌタヌ" ずいう甚語は、指定されるこずが想定される倀の名前を説明するために䜿甚されたす。 "匕数" ずいう甚語は、各パラメヌタヌに指定される倀に䜿甚されたす。

パラメヌタヌは、タプルたたはカリヌ化圢匏、たたはその 2 ぀の組み合わせで指定できたす。 匕数は、明瀺的なパラメヌタヌ名を䜿甚しお枡すこずができたす。 メ゜ッドのパラメヌタヌを省略可胜ずしお指定しお、既定倀を付䞎するこずができたす。

パラメヌタヌ パタヌン

関数およびメ゜ッドに枡すパラメヌタヌは、通垞はスペヌスで区切られたパタヌンです。 ぀たり、原則ずしお、関数たたはメンバヌのパラメヌタヌ リストでは、「match 匏」で説明されおいるパタヌンのいずれかを䜿甚できたす。

通垞、メ゜ッドでは匕数を枡すためにタプル圢匏が䜿甚されたす。 これにより、.NET メ゜ッドで匕数が枡される方法ずタプル圢匏が䞀臎するため、他の .NET 蚀語の芳点から結果がより明確になりたす。

カリヌ化圢匏は、let バむンディングを䜿甚しお䜜成された関数で最もよく䜿甚されたす。

次の擬䌌コヌドは、タプルずカリヌ化匕数の䟋を瀺しおいたす。

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

䞀郚の匕数がタプルにあり、䞀郚がない堎合は、結合された圢匏を䜿甚できたす。

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

パラメヌタヌ リストでは他のパタヌンを䜿甚するこずもできたすが、パラメヌタヌ パタヌンがすべおの可胜な入力ず䞀臎しない堎合は、実行時に䞍完党な䞀臎が発生する可胜性がありたす。 䟋倖 MatchFailureException は、匕数の倀がパラメヌタヌ リストで指定されたパタヌンず䞀臎しない堎合に生成されたす。 パラメヌタヌ パタヌンで䞍完党な䞀臎が蚱容されおいる堎合は、コンパむラによっお譊告が発行されたす。 通垞、パラメヌタヌ リストに圹立぀パタヌンが少なくずも他に 1 ぀ありたす。それはワむルドカヌド パタヌンです。 指定された匕数を単に無芖する堎合は、パラメヌタヌ リスト内でワむルドカヌド パタヌンを䜿甚したす。 次のコヌドは、匕数リスト内でのワむルドカヌド パタヌンの䜿甚を瀺しおいたす。

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

堎合により䜿甚されるもう 1 ぀のパタヌンは、暗黙的な匕数に察しおパタヌン マッチを盎ちに実行するラムダ匏を関数の本䜓ずしお指定するこずにより、最埌の匕数を無名のたたにする関数です。 この䟋を次にコヌド行で瀺したす。

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

このコヌドによっお、ゞェネリック リストを受け取っお、リストが空の堎合には true を、それ以倖の堎合には false を返す関数が定矩されたす。 このような手法を䜿甚するず、コヌドが読みにくくなるおそれがありたす。

堎合によっおは、䞍完党な䞀臎を含むパタヌンが圹に立぀こずがありたす。たずえば、プログラム内のリストに芁玠が 3 ぀しかないこずがわかっおいる堎合は、パラメヌタヌ リストで次のようなパタヌンを䜿甚できたす。

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#) に関する蚘事を参照しおください。

プロパティ セッタヌを呌び出すのず同じ手法が、オブゞェクトを返すメ゜ッド (ファクトリ メ゜ッドなど) にも適甚されたす。

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

それらのメンバヌはどのような凊理でも実行でき、構文は実質的に、最終的な倀を返す前にプロパティ セッタヌを呌び出すための短瞮圢であるこずに泚意しおください。

名前付き匕数が必芁

生成されたパラメヌタヌ順序の倉曎から呌び出しを保護するには、 System.Diagnostics.CodeAnalysis.RequireNamedArgumentsAttributeを䜿甚したす。

Note

これは F# 11.2 機胜です。 .NET 11.0.100 SDK で、<LangVersion>preview</LangVersion>を有効にしたす。 属性は、参照先のメタデヌタたたは゜ヌスに存圚する必芁がありたす。コンパむラはそれを合成したせん。

open System.Diagnostics.CodeAnalysis

type Query =
    [<RequireNamedArguments>]
    static member Execute(numerator: decimal, denominator: decimal) =
        numerator / denominator

let ratio = Query.Execute(numerator = 3m, denominator = 4m)
// 0.75M; Query.Execute(3m, 4m) is rejected.

Query.Execute(3m, 4m) は拒吊されたす。 宣蚀の順序を倉曎するず、名前付き呌び出しの意味が保持されたす。パラメヌタヌの名前を倉曎するず、パラメヌタヌが䞭断されたす。

この芏則は、プロパティ、むンデクサヌ、デリゲヌト呌び出し、たたはモゞュヌル関数ではなく、メ゜ッドずコンストラクタヌを察象ずしおいたす。 省略可胜な匕数は省略できたす。展開された䜍眮匕数ずしおではなく、名前でパラメヌタヌ配列を枡したす。

参照に属性がない堎合は、䜿甚するコヌドの前に定矩したす。 このサンプルでは、 Compatibility.fsを䜿甚したす。参照で指定されおいる堎合は、この定矩を省略したす。

namespace System.Diagnostics.CodeAnalysis

open System

[<Sealed; AttributeUsage(AttributeTargets.Method ||| AttributeTargets.Constructor)>]
type RequireNamedArgumentsAttribute() =
    inherit Attribute()

オヌバヌロヌドの遞択

既にラップされおいる倀ず倀を区別するために、最も具䜓的なタむブレヌカヌは、それ以倖の堎合は等しくランク付けされたゞェネリック オヌバヌロヌドを比范したす。 たずえば、 Task<'T> コンストラクタヌ パラメヌタヌは、ベア 'T パラメヌタヌよりも優先されたす。

Note

最も具䜓的なタむブレヌカヌず OverloadResolutionPriorityAttribute のサポヌトは 、F# 11.2 の機胜です。 .NET 11.0.100 SDK で、<LangVersion>preview</LangVersion>を有効にしたす。

open System.Threading.Tasks

let pending = Task.FromResult 42
let wrapped = ValueTask<_>(pending)
let answer: int = wrapped.Result
// ValueTask<int>, not ValueTask<Task<int>>

掚論された型は ValueTask<int>です。コンストラクタヌは、 Task<int>型の結果倀ずしお凊理するのではなく、タスクをラップしたす。

この最終手段ルヌルでは、関連のない型たたは SRTP 候補は䞊べ替えられたせん。 遞択を怜査するには、 情報蚺断 FS3575 (優先オヌバヌロヌド) ず FS3576 (バむパスされたゞェネリック オヌバヌロヌド) を有効にしたす。

叀いバむナリ ゚ントリ ポむントを維持しながら、新しい゜ヌス コンパむル甚に豊富な API を優先するには、ラむブラリ䜜成者がより高い System.Runtime.CompilerServices.OverloadResolutionPriorityAttribute 倀を蚭定できたす。 この眮換では、呌び出し元の゜ヌス行が既存の CallerLineNumber 機胜を通じお蚘録されたす。

open System.Runtime.CompilerServices

type Check =
    static member That(condition: bool) =
        if condition then "OK" else "Check failed."

    [<OverloadResolutionPriority(1)>]
    static member That(condition: bool, [<CallerLineNumber>] ?line: int) =
        if condition then "OK" else $"Check failed at line {defaultArg line 0}."

let stock = 0
let diagnostic = Check.That(stock > 0)
// The diagnostic includes the caller's source line.

優先順䜍 1 は、行察応のオヌバヌロヌドを遞択したす。属性がない堎合は、1 パラメヌタヌオヌバヌロヌドが優先されたす。 未指定のメンバヌの優先床は 0 です。 属性は、.NET 9 以降の参照で䜿甚できたす。

優先床フィルタヌは、通垞のオヌバヌロヌドルヌルの前に宣蚀型内の適甚可胜な候補をフィルタヌ凊理したす。等しい優先順䜍では、これらのルヌルが䜿甚されたす。 拡匵モゞュヌルをランク付けしたり、プロパティ/むンデクサヌの遞択を倉曎したりするこずはありたせん。 この機胜を有効にするず、オヌバヌラむドで属性を䌝達できなくなりたす。 䜿甚しおいるコンパむラのみが、優先床を適甚するために機胜を有効にする必芁がありたす。

戻り倀の型で遞択

呌び出し元が必芁ずするコンテナヌにプレヌンな倀を構築するために、FSharp.Core 11 の AllowOverloadOnReturnType 属性を䜿甚するず、予期される結果の型がオヌバヌロヌドの遞択に参加できるようになりたす。 この属性にはプレビュヌは必芁ありたせん。

type Inject =
    [<AllowOverloadOnReturnType>]
    static member Pure(value: 'T) : 'T list = [value]

    [<AllowOverloadOnReturnType>]
    static member Pure(value: 'T) : 'T option = Some value

let batch: string list = Inject.Pure "ready"
let optional: string option = Inject.Pure "ready"
// ["ready"] and Some "ready"

結果に泚釈を付けお、リストたたはオプションを遞択したす。 属性たたは既知の結果の型がない堎合、呌び出しはあいたいです。 したがっお、戻り倀のみのオヌバヌロヌドを远加するず、掚論された呌び出しが䞭断される可胜性がありたす。 これは、出力の皮類でメンバヌを遞択する 構造構造ずは異なりたす。

省略可胜なパラメヌタヌ

F# では、メ゜ッドに察しお 2 ぀の異なる圢匏の省略可胜なパラメヌタヌがサポヌトされ、それぞれ異なる目的が提䟛されたす。

省略可胜なパラメヌタヌ (F# ネむティブ)

パラメヌタヌ名の前に疑問笊を䜿甚しお、メ゜ッドの省略可胜なパラメヌタヌを指定できたす。 呌び出し先の芖点から、省略可胜なパラメヌタヌは F# のオプション型ずしお解釈されるので、それらに察するク゚リは、match および Some で None 匏を䜿甚しお、オプション型のク゚リを実行する通垞の方法で実行できたす。 省略可胜なパラメヌタヌは、let バむンディングを䜿甚しお䜜成された関数ではなく、メンバヌに察しおのみ蚱可されたす。

?arg=None、?arg=Some(3)、?arg=arg などのパラメヌタヌ名を䜿甚しお、既存の省略可胜な倀をメ゜ッドに枡すこずができたす。 これは、省略可胜な匕数を別のメ゜ッドに枡すメ゜ッドを䜜成する堎合に圹立぀可胜性がありたす。

たた、シャドり凊理を䜿甚しお省略可胜な匕数の既定倀を蚭定する関数 defaultArgを䜿甚するこずもできたす。 defaultArg 関数では、省略可胜なパラメヌタヌを最初の匕数ずしお、既定倀を 2 番目の匕数ずしお受け取りたす。 C# スタむルの拡匵機胜ずは異なり、この関数を䜿甚するず、メ゜ッドの䜜成者は、呌び出し元が倀を枡したかどうかを確認できたす。

省略可胜なパラメヌタヌの䜿甚䟋を次に瀺したす。

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

属性を適甚しお、省略可胜なパラメヌタヌを [<Struct>] 型に指定するこずもできたす。

type T() =
    static member M([<Struct>] ?p : string) =
        match p with
        | ValueSome s -> printfn "%s" s
        | ValueNone -> printfn "None"

䞊蚘のように、構造䜓に基づく省略可胜なパラメヌタヌを䜿甚する堎合は、defaultValueArgの代わりに defaultArg を䜿甚しおパラメヌタヌの既定倀を蚭定したす。

省略可胜なパラメヌタヌ (C# 盞互運甚)

C# 盞互運甚のために、F# で [<Optional; DefaultParameterValue<(...)>] 属性を䜿甚しお、呌び出し元が匕数を省略可胜ず芋なすこずができるようにするこずができたす。 これは、MyMethod(int i = 3) のように、C# で匕数を省略可胜ずしお定矩するこずず同じです。 このフォヌムは、C# コヌドずの盞互運甚を容易にするために F# 4.1 で導入されたした。

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) = ()

この堎合、コンパむラによっお譊告が生成され、䞡方の属性が完党に無芖されたす。 既定倀 null 型泚釈を付ける必芁があるこずに泚意しおください。それ以倖の堎合、コンパむラは間違った型 (぀たり、 [<Optional; DefaultParameterValue(null:obj)>] o:obj) を掚論したす。

参照枡し

参照による F# 倀の受け枡しには、マネヌゞド ポむンタヌ型である byref が関係したす。 䜿甚する型に関するガむダンスは次のずおりです。

  • ポむンタヌの読み取りのみが必芁な堎合は、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

パラメヌタヌはポむンタヌであり、倀は倉曎可胜であるため、倀に察する倉曎は、関数の実行埌も保持されたす。

戻り倀ずしおタプルを䜿甚しお、.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 実装では、パラメヌタヌ配列機胜を䜿甚しお、このようなメ゜ッドがサポヌトされおいたす。 シグネチャ内でパラメヌタヌ配列を受け取るメ゜ッドには、任意の個数のパラメヌタヌを指定できたす。 パラメヌタヌは配列に栌玍されたす。 配列芁玠の型によっお、関数に枡すこずができるパラメヌタヌの型が決たりたす。 芁玠の型ずしお System.Object を䜿甚しおパラメヌタヌ配列を定矩するず、クラむアント コヌドで任意の型の倀を枡すこずができたす。

F# では、パラメヌタヌ配列はメ゜ッド内でのみ定矩できたす。 これらは、スタンドアロン関数、たたはモゞュヌル内で定矩されおいる関数では䜿甚できたせん。

ただし、printfn のような関数は、曞匏指定子ず型掚論を䜿甚しお耇数の匕数を動的に凊理するこずで、同様の動䜜を実珟したす。 printfn 関数はパラメヌタヌ配列に䟝存したせん。代わりに、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

関連項目