Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use Named Arguments in F#

Calling a Dictionary's Add() method using named arguments works in F#.

let d = Dictionary<string, obj>()
d.Add(key = "five", value = 5)

let d2= Dictionary<obj, obj>()
d2.Add(key = "five", value = 5)
d2.Add(key = 5, value = 5)

In Polly's Context class , there is a similar Add() method with 2 overloads:

Add(key: obj, value: obj) : unit
Add(key: string, value: obj) : unit

And I can use it in all of these ways:

let c = Polly.Context()
c.Add("five", 5)
c.Add(5, 5)
c.Add(key = 5, value = 5)

But not this way, it says it can't resolve between the overloads and needs a type annotation.

c.Add(key = "five", value = 5)

Why is that and how can I fix it?

like image 357
Brett Rowberry Avatar asked Jul 13 '18 01:07

Brett Rowberry


People also ask

How do you handle a named argument in a function?

When you mix named and unnamed arguments in a function call, the unnamed arguments must come before the named ones in the argument list. Thus, when writing a function, you should put required arguments to the function in the argument list before the ones that you consider optional.

How do you specify a keyword arguments in function?

Keyword arguments (or named arguments) are values that, when passed into a function, are identifiable by specific parameter names. A keyword argument is preceded by a parameter and the assignment operator, = . Keyword arguments can be likened to dictionaries in that they map a value to a keyword.

Where do you put the arguments to a function?

Arguments are specified after the function name, inside the parentheses. You can add as many arguments as you want, just separate them with a comma.


1 Answers

The compiler cannot work out which method to use. This is more common when dealing with C# and OO style in general with F#. I don't mind, keeps me functionally honest.

The most straightforward way to fix your problem now would be to use:

c.Add(key = ("five" :> obj), value = 5)

By casting it there is no ambiguity about what the type is and the compiler is happy.

Alternatively, you could create a function with explicit types and this will help the compiler figure it out as well. If you are using this a lot I suggest this:

let addToPolly (ctx:Polly.Context) (k:obj) (v:obj) =
        ctx.Add(k,v)
        ignore()

addToPolly c "five" 5

UPDATE: As @brett pointed out I had inferred the answer but not been explicit. Here are some examples where the compiler is happy.

let pollyAddAsString (ctx:Polly.Context) (k:string) (v:obj) = ctx.Add(key = k, value = v) |> ignore
let pollyAddAsObj (ctx:Polly.Context) (k:obj) (v:obj) = ctx.Add(key = k, value = v) |> ignore
pollyAddAsObj c "five" 5
pollyAddAsString c "five" 5

let (k:string,v:obj) = ("five", 5 :> obj)
let (x:obj,y:obj) = ("five" :> obj, 5 :> obj)
c.Add(key = k, value = v)
c.Add(key = x, value = y)
like image 102
Devon Burriss Avatar answered Nov 15 '22 07:11

Devon Burriss