Syntax 如何在F中引用任意大小的元组的特定成员#

Syntax 如何在F中引用任意大小的元组的特定成员#,syntax,f#,tuples,Syntax,F#,Tuples,好吧,这可能是个愚蠢的问题 我有一些大小为4的元组,比如(int,int,int,int) 如果它是一个2元组,我可以使用fst(myTuple)来引用第一个元素。比如说,我怎么能引用4元组的第三个元素呢 使用模式匹配: let tup = 1, 2, 3, 4 let _,_,third,_ = tup printfn "%d" third // displays "3" 这在元组的MSDN文档中有直接描述:如果希望随机访问一般大小的元组,则不可能。对于任何给定的大小,您都可以遵循ildja

好吧,这可能是个愚蠢的问题

我有一些大小为4的元组,比如(int,int,int,int)

如果它是一个2元组,我可以使用fst(myTuple)来引用第一个元素。比如说,我怎么能引用4元组的第三个元素呢

使用模式匹配:

let tup = 1, 2, 3, 4
let _,_,third,_ = tup
printfn "%d" third // displays "3"

这在元组的MSDN文档中有直接描述:

如果希望随机访问一般大小的元组,则不可能。对于任何给定的大小,您都可以遵循ildjarn的答案(将其扩展为4、5等),但这是唯一的(功能性)方法


一般来说,元组的一种可能性是首先将其转换为列表,正如所发现的那样,但这并不太漂亮,因为它需要反射。

为了纯粹的新颖性,这里有一个重载运算符,适用于任何*大小的元组

let (@) t idx =
    match t.GetType().GetProperty(sprintf "Item%d" idx) with
    | null -> invalidArg "idx" "invalid index"
    | p -> p.GetValue(t, null) |> unbox

//Usage
let t = 4, 5, 6
let n1 : int = t@1 //4
let i = 2
let n2 = t@i //5

*在此上下文中,Any的含义更为有限,具体而言,最多为7。

这是@Daniels新奇解决方案的一个版本,它计算底层元组表示的
Rest
偏移量,以支持基于任意长元组的位置访问。忽略错误处理

let (@) t idx =
    let numberOfRests = (idx - 1) / 7
    let finalIdx = idx - 7 * numberOfRests
    let finalTuple =
        let rec loop curTuple curRest =
            if curRest = numberOfRests then curTuple
            else loop (curTuple.GetType().GetProperty("Rest").GetValue(curTuple, null)) (curRest+1)
        loop t 0

    finalTuple
     .GetType()
     .GetProperty(sprintf "Item%d" finalIdx)
     .GetValue(finalTuple, null) 
     |> unbox

//fsi usage:
> let i : int = (1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36)@36;;

val i : int = 36

如果你不合理地害怕模式匹配,你可以使用
ItemN
属性。@Daniel:我不相信在F#中,如果不使用反射或装箱,然后向下转换到相应的
系统,就可以访问这些属性。Tuple
首先键入。奇怪。我从没注意到。我假设它是有效的,因为它们被表示为
System.Tuple
s.@Daniel-我认为F#隐藏了它们,因为它支持无限长的元组:。净元组最多只有8个。在引擎盖下,F#将元组嵌套在第8位,表示长元组。太棒了,谢谢!我知道它必须是这样简单的。相关/重复问题:我可以原谅我没有考虑八元组吗?我很确定这可以递归处理idx>7@Mauricio谢弗-事实上,看看我刚刚发布的答案。