鉴于此运算符用于评估管道中的副作用
let inline (|>!) a f = f a ; a
Run Code Online (Sandbox Code Playgroud)
和这个代码片段
if 1 = 1 then
"same"
else
"different"
|>! printfn "The numbers are %s."
|> printfn "Yes, they are %s."
Run Code Online (Sandbox Code Playgroud)
这永远不会打印,The numbers are same但它会打印Yes, they are same。
为什么|>!这里忽略了副作用运算符,但|>考虑到了,尽管具有相同的缩进?
我是否必须以不同的方式定义副作用运算符?
像这样写它按预期工作。
if 1 = 1 then "same"
else "different"
|>! printfn "The numbers are %s."
|> printfn "Yes, they are %s."
Run Code Online (Sandbox Code Playgroud)
对我来说,代码实际上表现得好像写得一样不直观吗?
if 1 = 1 then
"same"
else
"different"
|>! printfn "The numbers are %s." // with indent here
|> printfn "Yes, they are %s."
Run Code Online (Sandbox Code Playgroud)
这不是错误,并且不会专门针对长度超过两个字符的运算符而发生。这是 F# 的宽松偏移规则的一个有趣的结果。
当对齐相同嵌套级别的行时,它们必须缩进相同,如下所示:
let foo =
bar
baz
qux
Run Code Online (Sandbox Code Playgroud)
但这是不允许的:
let foo =
bar
baz // Indented too much to the left
qux
Run Code Online (Sandbox Code Playgroud)
这也不是:
let foo =
bar
baz // Indented too little
qux
Run Code Online (Sandbox Code Playgroud)
在处理创建嵌套块的构造时,例如if/ then,此规则用于确定块何时结束:这是缩进对齐被破坏的时间。
let x =
if 1 = 1 then
bar
baz
qux
Run Code Online (Sandbox Code Playgroud)
但是这个规则有一个例外:如果该行以运算符开头,则允许最多向左移动运算符大小加 1 个字符,并且仍将其视为“当前”缩进.
例如,这有效:
let x =
1
+ 2
+ 3
Run Code Online (Sandbox Code Playgroud)
但是当你有不同规模的运营商时,它会变得棘手。这有效:
let x =
1
+ 2
+ 3
<> 6
Run Code Online (Sandbox Code Playgroud)
但这不会:
let x =
1
+ 2
+ 3
<> 6
Run Code Online (Sandbox Code Playgroud)
这并不工作,因为2和3被转移到左侧更比运营商大小加一个字符。
所以这就是你的情况:
printfn被认为是else块的一部分,因为它恰好与 对齐"different",但向左移动了运算符大小加一。printfn,然而,转移到由左更不是运营商大小加1,所以它的不再是一部分else。if/ then/else管道进去。1+2+3 <> 6上面的例子一样,但在这种情况下,语法恰好对齐(或者,可能只是错误)。您可以通过删除第二个前面的额外空间来验证这一点printfn:
if 1 = 1 then
"same"
else
"different"
|>! printfn "The numbers are %s."
|> printfn "Yes, they are %s."
Run Code Online (Sandbox Code Playgroud)
现在第二个printfn将成为 的一部分else,您将收到一个错误:types string and unit don't match。这是因为then返回 a string,但else现在返回 a unit。这可以通过修改then部分来解决:
if 1 = 1 then
()
else
"different"
|>! printfn "The numbers are %s."
|> printfn "Yes, they are %s."
Run Code Online (Sandbox Code Playgroud)
现在编译并且不打印任何内容。如果您替换1 = 1为1 = 2,它将正确打印两次“不同”。
最后,如果你想整个if/ then/else块通过两个管道输送printfn的呼叫,你必须打破的排列"different"与第一printfn莫名其妙。您为自己提供的一种方法:"different"与else. 另一种方法是缩进"different"一点,所以它不再与第一个对齐printfn:
if 1 = 1 then
"same"
else
"different"
|>! printfn "The numbers are %s."
|> printfn "Yes, they are %s."
Run Code Online (Sandbox Code Playgroud)