对于具有2个元素的基本元组,我们有fst和snd: let t2 = (2, 3)fst t2 // = 2snd t2 // = 3 简单.现在有3个元素 let t3 = (2, 3, 4) 我们如何访问第3个元素? msdn有一个答案(http://msdn.microsoft.com/en-us/libra
let t2 = (2, 3) fst t2 // = 2 snd t2 // = 3
简单.现在有3个元素
let t3 = (2, 3, 4)
我们如何访问第3个元素? msdn有一个答案(http://msdn.microsoft.com/en-us/library/dd233200.aspx):
let third (_, _, c) = c
还很容易.但实际上是欺骗性的,因为我们不能在这样的三元组上使用fst和snd:
fst t3 error FS0001: Type mismatch. Expecting a int * int but given a int * int * int The tuples have differing lengths of 2 and 3
因此,具有挑战性的问题是:如何在不牺牲运行时性能的情况下为元组,三元组和四元组提供函数fst?
方法不起作用:
A)简单地添加fst(,, _)
let fst (a,_,_) = a // hides fst (a,b), so tuples dont work anymore
B)任何反射技巧,因为性能受到影响或棘手的功能组合导致在jitted代码级别的额外调用.
C)扩展方法(没有引导我任何地方,也许别人有更好的想法)
type Tuple<'T1, 'T2, 'T3> with member o.fst(a,b,c) = a static member fst(a,b,c) = a
除了有其他签名(t3.fst())我甚至无法使用Tuples扩展,尽管它们是类(不是结构).
d)
let fst = function | (a,b) -> a | (a,b,c) -> a // FS0001: Type mismatch
这个问题意味着它的制定,而不是解决方法.实际上我相信答案是不可能提供在元组上运行的常用功能.
使用 this technique方法重载与内联函数相结合在运行时完全没有任何损失,因为重载解析发生在编译时,并且重载函数在调用站点处内联.有更复杂的方法可以在库中组织这些通用元组函数,@ MaicicioScheffer已经发布了一些链接,显示了更多使用基本相同技术的实验.
这是一个非常短的独立代码片段,用于重载函数fst以使其与其他元组大小一起使用:
type Fst = Fst with static member ($) (Fst, (x1,_)) = x1 static member ($) (Fst, (x1,_,_)) = x1 static member ($) (Fst, (x1,_,_,_)) = x1 // more overloads let inline fst x = Fst $x