F#-如何方便地将列表中的元素应用于当前函数';s参数?

F#-如何方便地将列表中的元素应用于当前函数';s参数?,f#,F#,假设有一个列表: let lst = [1;2;3] 和一个curried函数: let addAll a b c = a + b + c 如何使用listlst中的元素方便地输入当前函数的参数 一种方法是: addAll (lst |> List.item 0) (lst |> List.item 1) (lst |> List.item 2) 但这并不能很好地扩展!而且,这很无聊。很难从有限的示例中说出您的实际用例是什么。列表被设计为包含不同数量的项,函数采用固

假设有一个列表:

let lst = [1;2;3]
和一个curried函数:

let addAll a b c =
   a + b + c
如何使用list
lst
中的元素方便地输入当前函数的参数

一种方法是:

addAll (lst |> List.item 0) (lst |> List.item 1) (lst |> List.item 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
让lst=[1;2;3]
让我们把所有的东西都加起来=
a+b+c
设addAllVal=addAll
设f=addAllVal.GetType().GetMethod(“调用”[| typeof;typeof;typeof |])
让res=f.Invoke(addAllVal,Array.map框(Array.ofList lst)):?>int

从有限的示例中很难说您的实际用例是什么。列表被设计为包含不同数量的项,函数采用固定数量的项,因此两者不匹配。使用元组而不是列表可能更有意义:

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
让lst=[1;2;3]
让我们把所有的东西都加起来=
a+b+c
设addAllVal=addAll
设f=addAllVal.GetType().GetMethod(“调用”[| typeof;typeof;typeof |])
让res=f.Invoke(addAllVal,Array.map框(Array.ofList lst)):?>int

另一个选项是使用模式匹配:

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

另一个选项是使用模式匹配:

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

就我所知,没有办法按你的要求去做。如果您始终应用相同的操作,通常的处理方法是在列表上进行折叠。我在想这可能是一个。你有什么特别想实现的吗?据我所知,没有办法做到你所要求的。如果您始终应用相同的操作,通常的处理方法是在列表上进行折叠。我在想这可能是一个。您是否特别希望实现某些目标?反射是动态解决此类问题的良好起点。我们可以编写一个实用函数来包装所有反射代码,然后在其他地方优雅地使用它。但是,正如您所建议的,反射可能很慢……反射是动态解决此类问题的一个良好起点。我们可以编写一个实用函数来包装所有反射代码,然后在其他地方优雅地使用它。然而,正如您所建议的,反射可能会很慢……这肯定是另一种选择。但它仍然是手动的,就像我的方法一样。绝对是另一种选择。但它仍然像我的方法一样是手动的。