我编写了一个函数,它将一个数组作为输入,并返回一个大小相等的数组作为输出。例如:
myFunc [| "apple"; "orange"; "banana" |]
> val it : (string * string) [] =
[|("red", "sphere"); ("orange", "sphere"); ("yellow", "oblong")|]
现在我想通过let绑定来分配结果。例如:
let [|
( appleColor, appleShape );
( orangeColor, orangeShape );
( bananaColor, bananaShape )
|] =
myFunc [| "apple"; "orange"; "banana" |]
哪个效果很好......
> val orangeShape : string = "sphere"
> val orangeColor : string = "orange"
> val bananaShape : string = "oblong"
> val bananaColor : string = "yellow"
> val appleShape : string = "sphere"
> val appleColor : string = "red"
...除了它产生警告:
warning FS0025: Incomplete pattern matches on this expression. For example, the value '[|_; _; _; _|]' may indicate a case not covered by the pattern(s).
警告的来源和原因有already been covered,我只是在寻找一种简洁的解决方法。这个函数调用发生在我的函数顶部附近,我不喜欢把整个函数体放在匹配中的想法:
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!"
那闻起来很糟糕。我也不喜欢忽视警告的想法 - 违背我更好的判断。还有其他选择对我开放,还是我只需要完全找到不同的方法?
答案 0 :(得分:4)
如果你期望这种调用模式是频繁的,那么一种可能性就是制作一个与你期望的元组大小相关的包装器,例如。
myFunc3 (in1,in2,in3) =
match myFunc [|in1;in2;in3|] with
[|out1;out2;out3|] -> out1, out2, out3
_ -> failwith "Internal error"
等。但它所做的只是将丑陋的代码移动到标准位置,写出包装器会很不方便。
我认为这个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
然后在像
这样的块中使用它use myClass = new MyClass()
let appleColor, appleShape = myClass.MyFunc(apple)
...
答案 1 :(得分:0)
调整@Ganesh的答案,这是解决问题的一种原始方法:
let Tuple2Map f (u, v)
= (f u, f v)
let Tuple3Map f (u, v, w)
= (f u, f v, f w)
let Tuple4Map f (u, v, w, x)
= (f u, f v, f w, f x)
示例:
let Square x = x * x
let (a,b) = Tuple2Map Square (4,6)
// Output:
// val b : int = 36
// val a : int = 16
但我猜这个更原始的东西是这样的:
let Square x = x * x
let (a,b) = (Square 4, Square 6)
如果函数名称太长,例如
// Really wordy way to assign to (a,b)
let FunctionWithLotsOfInput w x y z = w * x * y * z
let (a,b) =
(FunctionWithLotsOfInput input1 input2 input3 input4A,
FunctionWithLotsOfInput input1 input2 input3 input4B)
我们可以定义临时功能
let FunctionWithLotsOfInput w x y z = w * x * y * z
// Partially applied function, temporary function
let (a,b) =
let f = (FunctionWithLotsOfInput input1 input2 input3)
(f input4A, f input4B)