F # - Как удобно применять элементы в списке к параметрам функции карри? - PullRequest
0 голосов
/ 02 декабря 2018

Предполагается, что есть список:

let lst = [1;2;3]

И функция с карри:

let addAll a b c =
   a + b + c

Как можно ввести параметры для функции с карри с условием , используяэлементы в списке lst?

Один из способов сделать это:

addAll (lst |> List.item 0) (lst |> List.item 1) (lst |> List.item 2)

Но это не очень хорошо масштабируется!Также скучно.

Ответы [ 2 ]

0 голосов
/ 02 декабря 2018

Другой вариант - использовать сопоставление с образцом:

let lst = [1;2;3]

match lst with [ a ; b; c] -> addAll a b c |_-> 0

возвращает 6.Если lst не имеет ровно 3 элемента, он возвращает 0, но вы можете изменить его для обработки других случаев:

let callAddAll lst =
    match lst with 
    | [              ]      ->            0
    | [ a            ]      -> addAll a 0 0
    | [ a  ; b       ]      -> addAll a b 0
    | [ a  ; b  ; c  ]      -> addAll a b c
    |   a :: b :: c :: rest -> addAll a b c  // ignore rest

[       ] |> callAddAll |> printfn "lst = %d"  // = 0
[1      ] |> callAddAll |> printfn "lst = %d"  // = 1
[1;2    ] |> callAddAll |> printfn "lst = %d"  // = 3
[1;2;3  ] |> callAddAll |> printfn "lst = %d"  // = 6
[1;2;3;4] |> callAddAll |> printfn "lst = %d"  // = 6
0 голосов
/ 02 декабря 2018

Трудно сказать из ограниченного примера, каков ваш реальный вариант использования.Списки составлены так, чтобы содержать различное количество элементов, а функции занимают постоянное количество элементов, поэтому они не соответствуют друг другу.Возможно, имеет смысл использовать кортеж, а не список:

let tup = (1,2,3)

let addAll (a, b, c) =
   a + b + c

addAll tup

Кортежи содержат фиксированное количество элементов, но их можно легко создавать и деконструировать, что позволит вам сразу передать все параметры в вашу функцию.

Вы также можете делать то, что просили об использовании отражения, но это может сломаться в будущих версиях F #, и это почти никогда не будет хорошим дизайном для простого случая, подобного этому.Это также медленно и, как вы можете видеть из числа downcasts и бокса, это также не очень безопасно:

let lst = [1;2;3]
let addAll a b c =
   a + b + c

let addAllVal = addAll
let f = addAllVal.GetType().GetMethod("Invoke", [| typeof<int>; typeof<int>; typeof<int> |]) 
let res = f.Invoke(addAllVal, Array.map box (Array.ofList lst)) :?> int
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...