我注意到,当您尝试编译时,以下代码会出错:
let xx =
seq {
let! i = [ 1; 2 ]
let! j = [ 3; 4 ]
yield (i,j)
}
Run Code Online (Sandbox Code Playgroud)
这给出的错误是" 错误FS0795:不再允许在序列表达式中使用'let!x = coll'.而是使用'for x in coll'. "这条消息当然是清楚的,并演示了如何解决它; 固定代码是:
let xx =
seq {
for i in [ 1; 2 ] do
for j in [ 3; 4 ] do
yield (i,j)
}
Run Code Online (Sandbox Code Playgroud)
我的问题不是如何解决这个问题,而是为什么"让!" 首先不允许在序列表达式中?我可以看到让我们这样的事实!迭代表达式可能会让一些人感到意外,但这不足以禁止构造.我也看到"for"在这里是如何更强大的,因为"let!"的版本 在迭代范围内烘焙为"直到序列表达式结束".
但是,能够迭代序列而不必缩进代码正是我所寻找的(用于遍历树结构).我假设要获得这个语义,我将不得不创建一个新的表达式构建器,其行为主要类似于"seq"表达式构建器,但允许"let!" 迭代,不是吗?
根据Brian的评论添加,为我的潜在问题提供解决方案:
我没有意识到for block中的缩进是不需要的,第二个样本可以重写为:
let xx =
seq {
for i in [ 1; 2 ] do
for j in [ 3; 4 ] do
yield (i,j)
}
Run Code Online (Sandbox Code Playgroud)
...当遍历树结构时,它摆脱了不断增加的缩进.语法甚至允许在两者之间附加声明的陈述,而不需要额外的缩进,如:
let yy =
seq {
for i in [ 1; 2 ] do
let i42 = i+42
for j in [ 3; 4 ] do
yield (i42,j)
}
Run Code Online (Sandbox Code Playgroud)
现在,如果我能弄清楚为什么我认为这些陈述需要缩进......
就在几周前,我和Don Syme一起写了一篇论文,试图解释F#计算表达式(如序列表达式,异步工作流等)中语法选择背后的一些动机.你可以在这里找到它.它没有给出你的问题的明确答案,但它可能有所帮助.
通常,当您有某种类型M<'T>
并且您正在定义计算构建器时,您可以添加方法For
并Bind
启用for
和let!
语法:
For : seq<'T> -> ('T -> M<'T>) -> M<'T>
Bind : M<'T> -> ('T -> M<'T>) -> M<'T>
Run Code Online (Sandbox Code Playgroud)
输入For
应始终为某个序列seq<'T>
,而输入Bind
应M<'T>
为您要定义的类型.
在序列表达式中,这两个操作将具有相同的类型,因此它们必须执行相同的操作.尽管序列表达式可以同时提供两者,但允许只有一个是一个好主意,因为对一件事使用两个不同的关键字会让人感到困惑.一般原则是comp { .. }
块中的代码应该像普通代码一样 - 并且由于for
存在于普通的F#代码中,因此在计算表达式中使用相同的语法是有意义的seq<'T>
.
归档时间: |
|
查看次数: |
640 次 |
最近记录: |