【问题标题】:How F# inlining of ignore function works regarding side effect functions忽略函数的 F# 内联如何处理副作用函数
【发布时间】:2021-05-17 09:21:37
【问题描述】:

我正在阅读这个answer,我想知道ignore 函数是如何内联的:它的参数应该被丢弃,但副作用仍然会发生:

// See https://github.com/dotnet/fsharp/blob/main/src/fsharp/FSharp.Core/prim-types.fs
let inline (|>) x f = f x
let inline ignore _ = ()

// Side effect function returning a value to ignore
let ok () =
    printfn "ok"
    true

// Usage
let t1 = ok () |> ignore
//     = ignore (ok ()) // `|>` inlined
//     = ()             // `ignore` inlined
//     what happened for `printfn "ok"` inside the `ok` function?

控制台输出:

ok
val ok : unit -> bool
val t1 : unit = ()

在 FSI 中执行代码时,编译时会打印“ok”(因为它出现在 val ok : unit -> bool 之前)。

→ 执行.fs 文件中的代码会发生什么?

【问题讨论】:

    标签: f#


    【解决方案1】:

    首先,F# interactive 的输出有点令人困惑 - 它在编译时不运行函数。它首先编译代码,然后运行它,然后打印所有结果的结果类型和值。它需要在打印之前运行代码,因为它还会打印最终值。

    至于发生了什么,让我们看看如果你刚刚:

    let ok () = printfn "ok"; true
    
    • 我们从let t1 = ok () |> ignore开始
    • 内联|> 后,变为let t1 = ignore(ok())
    • 内联ignore 后,变为let t1 = ok(); ()
    • 现在您有了一个使用; 组成的表达式,因此F# 计算第一个子表达式,即对ok() 函数的调用。你得到let t1 = (printf "ok"; true); ()
    • 表达式是从左到右计算的,所以这会运行打印(执行副作用)并且 printf 的结果是一个单位值()。所以我们现在有了let t1 = ((); true); ()
    • 现在,; 运算符被求值,() 被丢弃。我们有let t1 = true; ()
    • 现在,计算第二个; 运算符并丢弃true。我们有let t1 = ()。这就是最终结果!

    【讨论】:

      猜你喜欢
      • 2015-03-08
      • 2018-01-06
      • 2016-07-12
      • 1970-01-01
      • 2019-11-10
      • 2016-03-10
      • 1970-01-01
      • 2013-07-25
      • 1970-01-01
      相关资源
      最近更新 更多