f# - 为什么 Seq.map 只评估 5 个元素?
问题描述
这段代码:
[0..100]
|> Seq.map (fun i -> printfn "%A" i)
仅迭代 5 个元素:
> [0..100]
- |> Seq.map (fun i -> printfn "%A" i);;
0
1
2
3
4
val it : seq<unit> = seq [(); (); (); (); ...]
为什么?如何强制它评估所有元素?
解决方案
这发生在这里:表达式
[0..100] |> Seq.map (fun i -> printfn "%A" i)
计算成一系列单位,可视化为“()”。这不是您通常想要的。您可以看到地图内的函数通过 FSI 的(f# 交互)输出返回单位:
val it : seq<unit> = seq [(); (); (); (); ...]
如果你写,你会得到相同的结果
[0..100] |> Seq.map (fun _ -> ())
但与 (fun _ -> ()) 相比,函数 (fun i -> printfn "%A" i) 具有打印到控制台的副作用。这就是为什么您会在结果 [();之前看到打印的数字的原因。(); (); ()]
打印 5 个数字的原因是 FSI 内部:当它打印序列时,它们是可枚举的集合,它只枚举前几个。这里它枚举前5个元素并显示前4个,即[(); (); (); ()]
你真正想要的是一个接受一个值并返回一个新值的 map 函数,换句话说,一个将一个值映射到另一个值的函数:
[0..100] |> Seq.map (fun i -> i * 2)
val it : seq<int> = seq [0; 2; 4; 6; ...]
如您所见,这将返回序列的结果。同样,FSI 仅显示序列的前几个元素。如果将序列转换为列表,您会看到更多元素(但仍然不是全部,因为 100 太多了):
[0..100] |> Seq.map (fun i -> i * 2) |> Seq.toList
val it : int list =
[0; 2; 4; 6; 8; 10; 12; 14; 16; 18; 20; 22; 24; 26; 28; 30; 32; 34; 36; 38;
40; 42; 44; 46; 48; 50; 52; 54; 56; 58; 60; 62; 64; 66; 68; 70; 72; 74; 76;
78; 80; 82; 84; 86; 88; 90; 92; 94; 96; 98; 100; 102; 104; 106; 108; 110;
112; 114; 116; 118; 120; 122; 124; 126; 128; 130; 132; 134; 136; 138; 140;
142; 144; 146; 148; 150; 152; 154; 156; 158; 160; 162; 164; 166; 168; 170;
172; 174; 176; 178; 180; 182; 184; 186; 188; 190; 192; 194; 196; 198; ...]
这个缩写来自FSI,它终止了表达式输出的长度。您可以使用 fsi.PrintLength、PrintWidth 等配置这些输出的长度。请参阅文档。
如果要枚举列表序列的所有元素,可以编写实用函数,例如
let plo xs = xs |> Seq.iter (printfn "%O")
[0..10] |> Seq.map (fun i -> i * 2) |> Seq.toList |> plo
>
0
2
4
6
8
10
12
14
16
18
20
val it : unit = ()
推荐阅读
- flutter - 如何在 Flutter 中制作图标按钮重叠容器小部件?
- javascript - 无法使用文本输入值更新 React 状态
- android - 如何在 Kotlin 中为环境设置不同的常量
- javascript - Electronjs Mysql数据库提交查询随机访问
- reactjs - 如何在 Create-React-App 中实现 MobX?
- c# - 对话框在 MS BotFramework v4 的新对话中保留其变量值
- azure - 插入行时触发 Azure 逻辑应用
- python - 气流 list_dags 没有用变量识别 dag
- r - r:在函数中使用参数列表
- python - AWS Lambda 使用 python boto3 列出 EC2 实例 ID