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

标签 f#

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

let inline (|>!) a f = f a ; a 
和这个代码片段
if 1 = 1 then  
    "same"
else 
    "different"  
|>! printfn "The numbers are %s." 
|>  printfn "Yes, they are %s." 
这从不打印 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." 
对我来说,代码实际上表现得好像是写的那样只是不直观吗?
if 1 = 1 then  
    "same"
else 
    "different"  
    |>! printfn "The numbers are %s." // with indent here
|>  printfn "Yes, they are %s." 

编辑:
另见https://github.com/fsharp/fslang-suggestions/issues/806寻求答案。

最佳答案

这不是一个错误,并且不会专门针对超过两个字符的运算符发生。这是 F# 允许偏移规则的一个有趣结果。
当对齐相同嵌套级别的行时,它们必须在相同的缩进处,如下所示:

let foo =
     bar
     baz
     qux
但这是不允许的:
let foo =
     bar
      baz  // Indented too much to the left
     qux
这也不是:
let foo =
     bar
    baz  // Indented too little
     qux
在处理创建嵌套 block 的结构时,例如 if/then ,此规则用于确定 block 何时结束:即当缩进对齐被破坏时。
let x =
     if 1 = 1 then
       bar
       baz
     qux
但这条规则有一个异常(exception):如果该行以运算符开头,则最多允许向左移动运算符大小加上 1 个字符,并且仍将其视为“当前”缩进 .
例如,这有效:
let x =
       1
     + 2
     + 3
但是当你有不同规模的运营商时,它变得很棘手。这有效:
let x =
       1
     + 2
     + 3
    <> 6
但这不会:
let x =
        1
     +  2
     +  3
     <> 6
👆 这不起作用,因为 23向左移动 更多 比操作符大小加一个字符。

所以这就是你的情况:
  • 第一个printfn被认为是 else 的一部分 block ,因为它恰好与 "different" 对齐, 但左移运算符大小加一。
  • 第二个printfn但是,左移 更多 比运算符大小加一,所以它不再是 else 的一部分.
  • 但它仍然是正确的语法,因为现在它可以是周围 block 的一部分,整个结果为 if/then/else注入(inject)其中。
  • 通常你会得到一个语法错误,就像我的例子中的 1+2+3 <> 6上面,但在这种情况下,语法恰好对齐(或者,也许,只是错误)。

  • 您可以通过删除第二个 printfn 前面的多余空格来验证这一点。 :
    if 1 = 1 then  
        "same"
    else 
        "different"  
    |>! printfn "The numbers are %s." 
     |> printfn "Yes, they are %s." 
    
    现在第二个printfn将成为 else 的一部分,你会得到一个错误:types string and unit don't match .这是因为 then返回 string , 但是 else现在返回 unit .这可以通过修改 then 来解决。部分:
    if 1 = 1 then  
        ()
    else 
        "different"  
    |>! printfn "The numbers are %s." 
     |> printfn "Yes, they are %s." 
    
    现在这个编译并且不打印任何东西。如果你替换 1 = 11 = 2 ,它将正确打印“不同”两次。
    最后,如果你想要整个 if/then/else要通过两个 printfn 管道传输的 block 调用,你必须打破 "different" 的对齐方式第一个 printfn不知何故。你自己提供了一种方法:把 "different"else 在同一行.另一种方法是缩进 "different"更进一步,所以它不再与第一个 printfn 对齐:
    if 1 = 1 then  
        "same"
    else 
          "different"  
    |>! printfn "The numbers are %s." 
    |>  printfn "Yes, they are %s." 
    

    关于f# - 不考虑 if-else 表达式后的缩进变化?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64784154/

    相关文章:

    F# TypeProvider "XMLProvider"给出 System.Exception

    反射以了解属性是否为选项类型

    c# - 如何使用 ITestFilterService 和/或 ITestFilterBuilder 以编程方式为 NUnit 3 创建自定义过滤器

    f# - f# 中的线程参数

    F# - 如何以递归方式编写嵌套循环?

    f# - 抽象类类型签名中的可选参数

    insert - F# 树 : Node Insertion

    wpf - FSC : error FS2024: Static linking may not use assembly that targets different profile with oxyplot example and FsXaml

    c# - 延续:我可以在 F# 异步工作流或 C# 异步函数中序列化延续吗?

    f# - 如何在 F# 中执行链式回调?