避免“模式不匹配”​​警告的替代方法

JDB*_*JDB 3 f# pattern-matching let-binding

我编写了一个函数,该函数将一个数组作为输入并返回一个大小相等的数组作为输出。例如:

myFunc [| "apple"; "orange"; "banana" |]
Run Code Online (Sandbox Code Playgroud)
> val it : (string * string) [] =
    [|("red", "sphere"); ("orange", "sphere"); ("yellow", "oblong")|]
Run Code Online (Sandbox Code Playgroud)

现在,我想通过let绑定分配结果。例如:

let [|
        ( appleColor, appleShape );
        ( orangeColor, orangeShape );
        ( bananaColor, bananaShape )
    |] = 
    myFunc [| "apple"; "orange"; "banana" |]
Run Code Online (Sandbox Code Playgroud)

哪个很棒...

> val orangeShape : string = "sphere"
> val orangeColor : string = "orange"
> val bananaShape : string = "oblong"
> val bananaColor : string = "yellow"
> val appleShape : string = "sphere"
> val appleColor : string = "red"
Run Code Online (Sandbox Code Playgroud)

...除了会产生警告:

warning FS0025: Incomplete pattern matches on this expression. For example, the value '[|_; _; _; _|]' may indicate a case not covered by the pattern(s).
Run Code Online (Sandbox Code Playgroud)

警告的来源和原因已经讨论过,我只是在寻找一种简洁的解决方法。这个函数调用发生在我函数的顶部附近,我不喜欢将整个函数体放在匹配中的想法:

let otherFunc =
    match myFunc [| "apple"; "orange"; "banana" |] with
    | [|
        ( appleColor, appleShape );
        ( orangeColor, orangeShape );
        ( bananaColor, bananaShape )
      |] ->
        // ... the rest of my function logic
    | _ -> failwith "Something impossible just happened!"
Run Code Online (Sandbox Code Playgroud)

那只是难闻的气味。我也不喜欢忽略警告的想法-与我的更好判断背道而驰。我还有其他选择吗,还是我只需要找到一种完全不同的方法?

GS *_*ica 5

如果您希望这种调用模式很常见,那么一种可能是使包装器作用于您期望的元组的大小,例如

myFunc3 (in1,in2,in3) =
    match myFunc [|in1;in2;in3|] with
    [|out1;out2;out3|] -> out1, out2, out3
    _ -> failwith "Internal error"
Run Code Online (Sandbox Code Playgroud)

等等。但是它所做的只是将丑陋的代码移到标准位置,而写出包装程序将很不方便。

我认为该API没有更好的选择,因为无法告诉编译器myFunc总是返回与传递的元素数量相同的元素。

另一种选择是myFunc用一个IDisposable类代替:

type MyClass() =
   let expensiveResource = ...


   member this.MyFunc(v) = ...calculate something with v using expensiveResource

   interface IDisposable with
       override this.Dispose() = // cleanup resource
Run Code Online (Sandbox Code Playgroud)

然后像这样在块中使用它

use myClass = new MyClass()
let appleColor, appleShape = myClass.MyFunc(apple)
...
Run Code Online (Sandbox Code Playgroud)