不考虑 if-else 表达式后的缩进变化?

Gos*_*win 4 f#

鉴于此运算符用于评估管道中的副作用

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)

Fyo*_*kin 7

这不是错误,并且不会专门针对长度超过两个字符的运算符而发生。这是 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)

这并不工作,因为23被转移到左侧比运营商大小加一个字符。


所以这就是你的情况:

  • 第一个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 = 11 = 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)