Как я могу обратиться к конкретному члену кортежа любого размера в F # - PullRequest
3 голосов
/ 10 марта 2011

хорошо, это может быть глупый вопрос.

Итак, у меня есть несколько наборов размером 4, например (int, int, int, int)

Если бы это был 2 кортеж, я мог бы использовать fst (myTuple) для ссылки на первый элемент. Как я могу, скажем, сослаться на третий элемент 4-го кортежа?

Ответы [ 4 ]

8 голосов
/ 10 марта 2011

Использовать сопоставление с образцом:

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

Это описано непосредственно в документации MSDN для кортежей: Кортежи (F #)

4 голосов
/ 10 марта 2011

Вот версия нового решения @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
3 голосов
/ 10 марта 2011

Для абсолютной новизны, вот перегруженный оператор, который работает для кортежей любого * размера.

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

* Любой, в этом контексте, имеет более ограниченное значение, в частности, до 7.

1 голос
/ 10 марта 2011

Если вам нужен произвольный доступ к кортежу общего размера, то это невозможно. Для любого заданного размера вы можете следовать ответу ildjarn (увеличив его на четыре, пять и т. Д.), Но это единственный (функциональный) способ.

В целом, для кортежей существует возможность сначала преобразовать их в список, как это найдено здесь , но это не слишком красиво, так как требует отражения.

...