F# - splat / unpacking参数列表

时间:2015-08-21 10:37:24

标签: f#

F#内置运算符/函数是否允许解压缩参数列表/元组并将其传递给函数调用?

使用示例:

// simple add function
let add (a1 : int) (a2 : int) (a3 : int) = a1 + a2 + a3

// what I want to achieve
let result = add (missing_operator)[1; 2; 3]

// or
let result' = add (missing_operator) (1, 2, 3)

// flattening list
let a = [1; 2; 3]
let b = [(missing_operator) a; 4; 5]

与Python *运算符类似

def add(a1, a2, a3):
   return a1 + a2 + a3

add(*[1,2,3])

或者应用(func_name,args_list)函数

apply(add, [1, 2, 3])

2 个答案:

答案 0 :(得分:10)

对于成对和三合一,预定义的运算符||><|||||><|||类似于|><|论证(monuple):

let add a b c = a + b + c

add <||| (1, 2, 3)
(1, 2, 3) |||> add

您可以自己添加此类操作符:

let (||||>) (a1, a2, a3, a4) func = func a1 a2 a3 a4

let foo u v x y = ( u + v ) * ( x + y )
(1, 2, 3, 4) ||||> foo

所有这些操作符也适用于非均匀类型。

如果您想放弃类型安全,以下工作(对于非空参数):

let invokeWith args op =
    let func = op.GetType().GetMethod("Invoke", args |> Array.map(fun a -> a.GetType()))
    func.Invoke(op, args)

add |> invokeWith [|1; 2; 3|]

也适用于非均匀参数类型:

let pad (a : string) l = a.PadRight(l)
pad |> invokeWith [| "a"; 12 |]

当然,一旦你放弃静态类型检查,你就可以独立完成了:

// compiles but throws at runtime
pad |> invokeWith [| "a"; None |]

,而

// does not compile
// ( "a", None ) ||> pad

答案 1 :(得分:3)

我认为在F#中这样做的一种惯用方法可能是这样的:

  // simple add function
  let add (a1 : int) (a2 : int) (a3 : int) = a1 + a2 + a3

  // what I want to achieve
  let result = match [1; 2; 3] with | [a;b;c] -> add a b c // pattern matching works on lists

  // or
  let result' = let (a,b,c) = (1, 2, 3) in add a b c // unpacking tuples

  // flattening list
  let a = [1; 2; 3]
  let b =                            // sequence expressions with yield!
    seq {
        yield! a
        yield 4
        yield 5
      } |> Seq.toList

  let c = [4; 5]
  let b' = 
    seq {
        yield! a
        yield! c
      } |> Seq.toList