如何在F#中设置默认参数值?

Nic*_*ick 11 f#

以此功能为例:

// Sequence of random numbers
open System

let randomSequence m n= 
    seq { 
        let rng = new Random()
        while true do
            yield rng.Next(m,n)
    }


randomSequence 8 39
Run Code Online (Sandbox Code Playgroud)

randomSequence函数有两个参数:m, n.这作为正常功能正常工作.我想设置默认值m, n,例如:

(m = 1, n = 100)
Run Code Online (Sandbox Code Playgroud)

如果没有给出参数,则该函数采用默认值.在F#中有可能吗?

Mar*_*ann 15

您通常可以通过Discriminated Union实现与重载相同的效果.

以下是基于OP的建议:

type Range = Default | Between of int * int

let randomSequence range = 
    let m, n =
        match range with
        | Default -> 1, 100
        | Between (min, max) -> min, max

    seq {
        let rng = new Random()
        while true do
            yield rng.Next(m, n) }
Run Code Online (Sandbox Code Playgroud)

请注意引入Range歧视联盟.

以下是一些(FSI)用法示例:

> randomSequence (Between(8, 39)) |> Seq.take 10 |> Seq.toList;;
val it : int list = [11; 20; 36; 30; 35; 16; 38; 17; 9; 29]

> randomSequence Default |> Seq.take 10 |> Seq.toList;;
val it : int list = [98; 31; 29; 73; 3; 75; 17; 99; 36; 25]
Run Code Online (Sandbox Code Playgroud)

另一种选择是稍微改变randomSequence以取一个元组而不是两个值:

let randomSequence (m, n) = 
    seq {
        let rng = new Random()
        while true do
            yield rng.Next(m, n) }
Run Code Online (Sandbox Code Playgroud)

这将允许您还定义默认,如下所示:

let DefaultRange = 1, 100
Run Code Online (Sandbox Code Playgroud)

以下是一些(FSI)用法示例:

> randomSequence (8, 39) |> Seq.take 10 |> Seq.toList;;
val it : int list = [30; 37; 12; 32; 12; 33; 9; 23; 31; 32]

> randomSequence DefaultRange |> Seq.take 10 |> Seq.toList;;
val it : int list = [72; 2; 55; 88; 21; 96; 57; 46; 56; 7]
Run Code Online (Sandbox Code Playgroud)

  • @Nick也许这很麻烦,但有时候,根据我的经验,对Discriminated Union的更改可以触发关于域的新见解,而新的Discriminated Union也可以用于其他功能,如[链接示例说明](http ://blog.ploeh.dk/2013/10/21/replace-overloading-with-discriminated-unions).无论如何,我用另一种方法更新了我的答案. (2认同)

Car*_*Dev 11

只允许成员使用可选参数[...]

https://msdn.microsoft.com/en-us/library/dd233213.aspx

所以,对于你目前的例子,我认为这是不可能的.但你可以包装功能:

type Random =
    static member sequence(?m, ?n) =
        let n = defaultArg n 100
        let rng = new System.Random()
        match m with
        | None -> Seq.initInfinite (fun _ -> rng.Next(1, n))
        | Some(m) -> Seq.initInfinite (fun _ -> rng.Next(m, n))
Run Code Online (Sandbox Code Playgroud)

然后像这样使用它:

let randomSequence = Random.sequence(2, 3)
let randomSequence' = Random.sequence(n = 200)
let randomSequence'' = Random.sequence()
Run Code Online (Sandbox Code Playgroud)

说明:可选参数可以是完全选项 al(m)或defaultArg s(n).我喜欢阴影(重用相同的名称)这些参数,但这是有争议的.


tha*_*alm 10

这似乎是这个问题最优雅的解决方案:

//define this helper function
let (|Default|) defaultValue input =
    defaultArg input defaultValue

//then specify default parameters like this
let compile (Default true optimize) = 
    optimize

//or as the OP asks
let randomSequence (Default 1 m) (Default 100 n) =
  seq { 
      let rng = new System.Random()
      while true do
          yield rng.Next(m,n)
  }
Run Code Online (Sandbox Code Playgroud)

学分:http : //fssnip.net/5z