F# 嵌套 List.iter 调用
F# nested List.iter calls
我有一个 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个结果,好好写。感谢您的任何建议。
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
对于像上传结果这样的纯命令式操作,我真的不会太担心。在您的代码示例中使用 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 个列表进行了优化)
事实上,您的主要目标是创建多个列表的叉积(或笛卡尔积),并且有几个F# 开发人员 "good practice" 考虑的选项:
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
我有一个 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个结果,好好写。感谢您的任何建议。
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
对于像上传结果这样的纯命令式操作,我真的不会太担心。在您的代码示例中使用 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 个列表进行了优化)
事实上,您的主要目标是创建多个列表的叉积(或笛卡尔积),并且有几个F# 开发人员 "good practice" 考虑的选项:
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