开发者

Convert out parameter of constructor to a tuple to use in pattern matching in F#

I have read that F# is smart enough to convert out parameter of a method to tuple. For example:

let isInt s =
  m开发者_如何学Pythonatch System.Int32.TryParse(s) with
  | (false, _) -> false
  | (true, _) -> true

I want to create a new Mutex with unique system-wide name. There's a constructor with 3 parameters:

new: 
    initiallyOwned:bool * 
    name:string * 
    createdNew:bool byref -> Mutex

Last parameter is out parameter and F# should be able to convert constructor call result to a tuple. Nevertheless the following code looks fails to compile with the error "This expression was expected to have type Mutex but here has type 'a * 'b"

open System.Threading

let rec CreateUniqueMutex i =
    match new Mutex(false, i.ToString()) with
    | (_, false) -> CreateUniqueMutex (i+1) // Error here
    | (mutex, true) -> mutex

What is the difference with the first isInt method?

Can my code be fixed?

What would be the best-looking code for my task?


The difference is that there are multiple overloads of the Mutex constructor, so the compiler thinks that you're calling the overload which takes exactly two arguments. Your best bet is to declare a mutable local and use that:

let rec createUniqueMutex i =
    let mutable b = false
    let mutex = new Mutex(false, string i, &b)
    if b then mutex else createUniqueMutex (i+1)

Note that I've fixed a few other issues with your code. In particular, you need to use let rec to define a recursive function and you need to parenthesize (i+1).

Edit

Just to show that this would work if it weren't for the overloads:

type MyType(x:string, [<System.Runtime.InteropServices.Out>]y:int byref) =
    do y <- 3
    member __.X = x

let (myT, n) = MyType("test")

As a minor point, note that the tuples in your match statement are backwards: the return value comes first, so they should be (_,false) and (mutex, true).

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜