David S.
David S.

Reputation: 11200

How to implement variable arguments in F#

I want to implement a F# function which may accept 1 or 2 arguments. I would like to use the function like this:

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

Both the arguments can be the same type. I read the pages about match pattern, active pattern, but cannot find one works for me.

Upvotes: 5

Views: 783

Answers (4)

Joh
Joh

Reputation: 2370

In addition to the other answers, here are a few more "almost solutions". They are not strictly what you wanted, but are worth knowing anyway.

Using a list (or an array) and pattern matching:

let f = function
    | [a, b] -> ...
    | [a] -> ...
    | [] -> failwith "too few arguments"
    | _ -> failwith "too many arguments"

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

Problems: parameters are not named, not clear from function signature how many parameters it takes.

Using a record to pass all optional parameters:

type FParams = { a : string; b : string }
let fdefault = { a = "a" ; b = "b" }

let f (pars: FParams) = ...

f { fdefault with b = "c" }

Problem: a is also optional, which is not what you wanted. Can be useful though.

Upvotes: 3

Onorio Catenacci
Onorio Catenacci

Reputation: 15343

In addition to the other answers, you might also be able to do what you want via partial application and currying. Like this:

let foo a b =
   a + b

let foo2 a =
   foo 1 a;;

Obviously you'd want to fix the first parameter in the call to foo within foo2 to whatever default you want.

Upvotes: 2

theburningmonk
theburningmonk

Reputation: 16071

On a type member, you can use optional params:

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

To call this method:

Helper.foo("a")
Helper.foo("a", "b")

Is this what you're after?

You can't use optional params on a function though, unfortunately.

Upvotes: 5

John Palmer
John Palmer

Reputation: 25526

I believe this is due to some of the underlying .Net features, but I think you have to use a class with overloaded methods - something like

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

Upvotes: 7

Related Questions