如何在 F# 中设置默认参数值?
How to set default argument value in F#?
以这个函数为例:
// Sequence of random numbers
open System
let randomSequence m n =
seq {
let rng = Random ()
while true do
yield rng.Next (m, n)
}
randomSequence 8 39
randomSequence
函数有两个参数:m, n
。这作为正常功能工作正常。我想为 m, n
设置默认值,例如:
(m = 1, n = 100)
当没有给定参数时,函数采用默认值。在 F# 中可以吗?
Optional parameters are permitted only on members [...]
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))
然后像这样使用它:
let randomSequence = Random.sequence(2, 3)
let randomSequence' = Random.sequence(n = 200)
let randomSequence'' = Random.sequence()
说明:可选参数可以完全是Optional (m)或defaultArg s (n)。我喜欢隐藏(重复使用相同的名称)这些参数,但这是有争议的。
let randomSequence m n=
seq {
let rng = new Random()
while true do
yield rng.Next(m,n)
}
let randomSequenceWithDefaults() =
randomSequence 1 100
因此,改为调用 randomSequenceWithDefaults()
你经常可以achieve the same effect as overloading with a 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) }
注意 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]
另一种选择是稍微更改 randomSequence 以采用元组而不是两个值:
let randomSequence (m, n) =
seq {
let rng = new Random()
while true do
yield rng.Next(m, n) }
这样您还可以定义默认的 值,如下所示:
let DefaultRange = 1, 100
以下是一些 (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]
这似乎是这个问题最优雅的解决方案:
//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)
}
以这个函数为例:
// Sequence of random numbers
open System
let randomSequence m n =
seq {
let rng = Random ()
while true do
yield rng.Next (m, n)
}
randomSequence 8 39
randomSequence
函数有两个参数:m, n
。这作为正常功能工作正常。我想为 m, n
设置默认值,例如:
(m = 1, n = 100)
当没有给定参数时,函数采用默认值。在 F# 中可以吗?
Optional parameters are permitted only on members [...]
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))
然后像这样使用它:
let randomSequence = Random.sequence(2, 3)
let randomSequence' = Random.sequence(n = 200)
let randomSequence'' = Random.sequence()
说明:可选参数可以完全是Optional (m)或defaultArg s (n)。我喜欢隐藏(重复使用相同的名称)这些参数,但这是有争议的。
let randomSequence m n=
seq {
let rng = new Random()
while true do
yield rng.Next(m,n)
}
let randomSequenceWithDefaults() =
randomSequence 1 100
因此,改为调用 randomSequenceWithDefaults()
你经常可以achieve the same effect as overloading with a 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) }
注意 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]
另一种选择是稍微更改 randomSequence 以采用元组而不是两个值:
let randomSequence (m, n) =
seq {
let rng = new Random()
while true do
yield rng.Next(m, n) }
这样您还可以定义默认的 值,如下所示:
let DefaultRange = 1, 100
以下是一些 (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]
这似乎是这个问题最优雅的解决方案:
//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)
}