如何在F#中实现可变参数

5

我希望实现一个 F# 函数,它可以接受 1 或 2 个参数。我想这样使用函数:

let foo = ...
foo "a"
foo "a" "b"

这两个参数可以是相同类型。 我阅读了关于匹配模式活动模式的页面,但没有找到适合我的。


回答问题是一个不好的习惯,你其实并不需要它,但这就是我想到的。如果你的参数是相同类型的值列表,只需将它们制作成 list。如果其中一个是可选的(例如可能有默认值可以省略),请将其设置为可选:foo(a, ?b)。如果您的数据可以用这种方式表示,也可以考虑使用 DU。否则,我会只使用两个函数。 - Be Brave Be Like Ukraine
4个回答

7

我认为这是由于一些底层的.Net特性,但我认为你必须使用具有重载方法的类 - 类似于

 type t() =
     static member foo a = "one arg"
     static member foo (a,b) = "two args"

5
请注意,第二个参数必须是元组,否则foo"a"会存在歧义,无法确定是调用第一种重载还是将第二种重载柯里化。 - Guvante

5

在类型成员上,您可以使用可选参数:

type Helper private () =
    static member foo (input1, ?input2) =
          let input2 = defaultArg input2 "b"
          input1, input2

调用此方法的方式如下:
Helper.foo("a")
Helper.foo("a", "b")

这是您想要的吗?

不幸的是,您不能在函数中使用可选参数。


3
除了其他答案,这里还有一些“几乎解决方案”。它们不是严格符合您的要求,但还是值得知道的。
使用列表(或数组)和模式匹配:
let f = function
    | [a, b] -> ...
    | [a] -> ...
    | [] -> failwith "too few arguments"
    | _ -> failwith "too many arguments"

f ["a"]
f ["a" ; "b"]

问题:函数参数未命名,从函数签名中无法清楚地了解需要多少个参数。
使用记录来传递所有可选参数:
type FParams = { a : string; b : string }
let fdefault = { a = "a" ; b = "b" }

let f (pars: FParams) = ...

f { fdefault with b = "c" }

问题:a也是可选的,这不是你想要的。但它可能会有用处。

2

除了其他答案之外,您还可以通过部分应用和柯里化来实现所需的功能。像这样:

let foo a b =
   a + b

let foo2 a =
   foo 1 a;;

显然,您需要在foo2内对foo的第一个参数进行修复,以便符合您想要的任何默认值。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接