0

假设有一个列表:

let lst = [1;2;3]

和一个咖喱函数:

let addAll a b c =
   a + b + c

如何使用 list 中的元素方便地输入curriedlst函数的参数?

一种方法是:

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

但这并不能很好地扩展!还有,很无聊。

4

2 回答 2

2

从有限的示例中很难说出您的实际用例是什么。列表旨在包含不同数量的项目,而函数采用恒定数量的项目,因此两者不能很好地匹配。使用元组而不是列表可能更有意义:

let tup = (1,2,3)

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

addAll tup

元组包含固定数量的项目,但它们可以很容易地构造和解构,并允许您一次将所有参数传递给您的函数。

您也可以按照您的要求执行有关使用反射的操作,但这可能会在 F# 的未来版本中中断,并且对于像这样的简单案例来说,它几乎从来都不是一个好的设计。它也很慢,从下投和拳击的数量可以看出,它也不是很安全:

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
于 2018-12-02T00:08:22.923 回答
2

另一种选择是使用模式匹配:

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
于 2018-12-02T00:30:47.863 回答