How can I refer to a specific member of a Tuple of any size in F#

前端 未结 4 986
囚心锁ツ
囚心锁ツ 2020-12-11 23:54

okay, this might be a silly question.

So I have some tuples of size 4 so like (int,int,int,int)

If it were a 2 tuple I could use fst(myTuple) to refer to th

相关标签:
4条回答
  • 2020-12-12 00:09

    Here's a version of @Daniels novel solution which calculates Rest offsets of the underlying Tuple representation to support position-based access on arbitrarily long tuples. Error handling omitted.

    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
    
    0 讨论(0)
  • 2020-12-12 00:22

    For the sheer novelty, here's an overloaded operator that works for tuples of any* size.

    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, in this context, has a more limited meaning, specifically, up to 7.

    0 讨论(0)
  • 2020-12-12 00:25

    Use pattern matching:

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

    This is described directly in the MSDN documentation for tuples: Tuples (F#)

    0 讨论(0)
  • 2020-12-12 00:28

    If you want random access to a generally sized tuple, then it is not possible. For any given size, you can follow ildjarn's answer (extending it for four, five, etc.), but that it the only (functional) way.

    A possibility for tuples in general, is to convert it to a list first, as found here, but that's not too pretty as it requires reflection.

    0 讨论(0)
提交回复
热议问题