F#嵌套List.iter调用

时间:2015-11-21 18:15:33

标签: loops f# iterator nested

我有一个F#功能,我想尝试改变一些参数并测试所有这些组合。这是正确的方法吗? (括号变得有点密集......):

let MyFunc a b c x y z = 
  ...
  q


let UploadResult a b c x y z q =
  ...
  ()


let a = 5.0
let b = 0
let c = System.DateTime.Today
let xList = [-1.0; 0.0; 1.0]
let yList = [2; 4; 6; 8; 10]
let zList = [0.1; 0.001]

xList  |> List.iter (fun x ->
(yList |> List.iter (fun y ->
(zList |> List.iter (fun z ->
MyFunc a b c x y z 
|> UploadResult a b c x y z ))) ))
|> ignore

所以我想上传3x5x2 = 30个结果,写得很好。谢谢你的建议。

3 个答案:

答案 0 :(得分:4)

对于像上传结果这样纯粹的必要操作,我真的不会太担心。在代码示例中使用List.iter可以解决问题。我可能更喜欢for循环,只是因为很明显这段代码具有重要的副作用:

for x in xList do
  for y in yList do
    for z in zList do
      MyFunc a b c x y z |> UploadResult a b c x y z

如果你想做一些聪明的事情,你可以编写一个函数,从两个列表中产生所有参数组合:

let product xl yl = 
  seq { for x in xl do
          for y in yl do
            yield x, y }

好消息是你也可以多次使用它:product xList (product yList zList)。这将为您提供一个可以再次迭代的元组列表:

for (x,y), z in product (product xList yList) zList do
    MyFunc a b c x y z 
    |> UploadResult a b c x y z

关于这一点的不太好的事情是你最终会得到嵌套的元组 - 这就是为什么我可能只使用一个简单的循环。 (或者,如果您总是有3个列表,那么另一个答案中的解决方案类似于product,但针对3个列表进行了优化)

答案 1 :(得分:2)

事实上,您的主要目标是创建多个列表的跨产品(或笛卡尔产品),并考虑了几个选项"良好做法& #34;在F#开发者中间:

1。 (删除了for - 理解,因为其他答案已经提出了这一点)

<强> 2。使用计算表达式(在函数式编程世界的其余部分,通常称为 Monad ):

type Product () =
    member this.Bind (l,f) = List.collect f l    
    member this.Return n = [n]

let ret02 = Product() {
    let! x = xList
    let! y = yList
    let! z = zList
    MyFunc a b c x y z
    |> UploadResult a b c x y z
}

3。如果您只是担心括号,请使用高优先级,右关联反向管道,(more info

let inline (^<|) f a = f a

然后,您的代码需要进行最小的修改(尽管仍然不是很干净):

let ret03 =
    xList  |> List.iter ^<| fun x ->
    yList  |> List.iter ^<| fun y ->
    zList  |> List.iter ^<| fun z ->
        MyFunc a b c x y z
        |> UploadResult a b c x y z
        |> ignore

答案 2 :(得分:1)

let MyFunc a b c x y z = 
    42

let UploadResult a b c x y z q =
    printfn "%A %A %A %A %A %A %A" a b c x y z q

let a = 5.0
let b = 0
let c = System.DateTime.Today
let xList = [-1.0; 0.0; 1.0]
let yList = [2; 4; 6; 8; 10]
let zList = [0.1; 0.001]

let perm xs ys zs =
    [for x in xs do
        for y in ys do 
            for z in zs do
                yield x,y,z]
let f (x,y,z) = MyFunc a b c  x y z |> UploadResult a b c  x y z
perm xList yList zList |> List.iter f